{"record":{"id":"cc77bc8803d7e440","repo":"unslothai/unsloth","slug":"num-frames-must-be-of-the-form-h3-frames-per-chun","errorCode":null,"errorMessage":"num_frames must be of the form {H3_FRAMES_PER_CHUNK} * n + {H3_LATENTS_PER_CHUNK}, got {num_frames}.","messagePattern":"num_frames must be of the form (.+?) \\* n \\+ (.+?), got (.+?)\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"studio/backend/core/training/diffusion_h3_clips.py","lineNumber":99,"sourceCode":"H3_TRAIN_NUM_FRAMES = H3_FRAMES_PER_CHUNK + H3_LATENTS_PER_CHUNK\n\n_VIDEO_EXTS = {\".mp4\", \".mov\", \".mkv\", \".webm\", \".m4v\", \".avi\"}\n_CAPTION_EXTS = (\".txt\", \".caption\")\n\n\ndef h3_align_num_frames(num_frames: int) -> int:\n    \"\"\"Snap a frame count UP to the next ``17 * n + 5`` the video VAE can encode.\"\"\"\n    if num_frames < 1:\n        raise ValueError(f\"num_frames must be positive, got {num_frames}.\")\n    while num_frames % H3_FRAMES_PER_CHUNK != H3_LATENTS_PER_CHUNK:\n        num_frames += 1\n    return num_frames\n\n\ndef h3_video_latent_frames(num_frames: int) -> int:\n    \"\"\"Latent frames the video VAE produces for an aligned frame count: ``5 * n + 2``.\"\"\"\n    if num_frames % H3_FRAMES_PER_CHUNK != H3_LATENTS_PER_CHUNK:\n        raise ValueError(\n            f\"num_frames must be of the form {H3_FRAMES_PER_CHUNK} * n + {H3_LATENTS_PER_CHUNK}, \"\n            f\"got {num_frames}.\"\n        )\n    return (num_frames - H3_LATENTS_PER_CHUNK) // H3_FRAMES_PER_CHUNK * H3_LATENTS_PER_CHUNK + 2\n\n\ndef h3_audio_latent_count(num_frames: int) -> int:\n    \"\"\"Audio latents (per channel) covering ``num_frames`` frames at 24 fps / 40 latents per s.\"\"\"\n    return int(round(num_frames / H3_FPS * H3_AUDIO_LATENTS_PER_SECOND))\n\n\ndef h3_audio_sample_count(num_frames: int) -> int:\n    \"\"\"Waveform samples per channel the audio VAE must be handed for ``num_frames`` frames.\n\n    The audio VAE hops 800 samples (32 kHz / 40 latents per second) and right-pads a short\n    tail, so handing it exactly ``latents * hop`` samples produces exactly the latent count the\n    packed layout reserves rows for -- no pad, no truncation.\"\"\"\n    hop = H3_AUDIO_SAMPLING_RATE // H3_AUDIO_LATENTS_PER_SECOND","sourceCodeStart":81,"sourceCodeEnd":117,"githubUrl":"https://github.com/unslothai/unsloth/blob/203007d19051dcd2ae33876786d117c99f6b0368/studio/backend/core/training/diffusion_h3_clips.py#L81-L117","documentation":"Raised by h3_video_latent_frames() when num_frames is not congruent to H3_LATENTS_PER_CHUNK (5) modulo H3_FRAMES_PER_CHUNK (17) — i.e. not of the form 17*n + 5. The video VAE only encodes aligned frame counts, so computing latent frames for any other count is undefined. Use h3_align_num_frames() first to snap the count up.","triggerScenarios":"Calling h3_video_latent_frames(30) or any count where num_frames % 17 != 5; passing a raw user-requested duration in frames that was never run through h3_align_num_frames().","commonSituations":"Computing memory/latent budgets from an arbitrary fps*seconds product; wiring a UI slider straight into latent math; copy-pasting a frame count from another model family (e.g. 24 or 25 fps clips).","solutions":["Run the count through h3_align_num_frames() before h3_video_latent_frames().","Use H3_TRAIN_NUM_FRAMES (the canonical 22-frame training clip) when in doubt.","Add a modulo assertion at your call site to catch unaligned counts early."],"exampleFix":"# before\nlatents = h3_video_latent_frames(requested_frames)  # e.g. 30 -> ValueError\n\n# after\nlatents = h3_video_latent_frames(h3_align_num_frames(requested_frames))","handlingStrategy":"validation","validationCode":"def frames_aligned(num_frames: int, per_chunk: int = 17, latents: int = 5) -> bool:\n    return num_frames % per_chunk == latents","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always run h3_align_num_frames() on raw frame counts before latent math.","Assert the 17*n+5 invariant in tests that touch frame/latent sizing."],"tags":["validation","video","minimax-h3","frame-count"],"backgroundTag":null,"analyzedSha":"203007d19051dcd2ae33876786d117c99f6b0368","analyzedAt":"2026-08-15T02:48:39.846Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}