{"record":{"id":"ce70890def765938","repo":"sgl-project/sglang","slug":"nframes-should-in-interval-frame-factor-total","errorCode":null,"errorMessage":"nframes should in interval [{FRAME_FACTOR}, {total_frames}], but got {nframes}.","messagePattern":"nframes should in interval \\[(.+?), (.+?)\\], but got (.+?)\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/sglang/srt/multimodal/processors/ernie45_vl.py","lineNumber":167,"sourceCode":"        \"fps\" in ele and \"nframes\" in ele\n    ), \"Only accept either `fps` or `nframes`\"\n    if \"nframes\" in ele:\n        nframes = round_by_factor(ele[\"nframes\"], FRAME_FACTOR)\n    else:\n        fps = ele.get(\"fps\", FPS)\n        min_frames = ceil_by_factor(ele.get(\"min_frames\", FPS_MIN_FRAMES), FRAME_FACTOR)\n        max_frames = floor_by_factor(\n            ele.get(\"max_frames\", min(FPS_MAX_FRAMES, total_frames)), FRAME_FACTOR\n        )\n        nframes = total_frames / video_fps * fps\n        if nframes > total_frames:\n            logger.warning(\n                f\"smart_nframes: nframes[{nframes}] > total_frames[{total_frames}]\"\n            )\n        nframes = min(min(max(nframes, min_frames), max_frames), total_frames)\n        nframes = floor_by_factor(nframes, FRAME_FACTOR)\n    if not (FRAME_FACTOR <= nframes and nframes <= total_frames):\n        raise ValueError(\n            f\"nframes should in interval [{FRAME_FACTOR}, {total_frames}], but got {nframes}.\"\n        )\n    return nframes\n\n\n# process video, qwen-specific\nasync def preprocess_video(\n    vr,\n    image_factor: int = IMAGE_FACTOR,\n) -> torch.Tensor:\n\n    total_frames, video_fps = len(vr), vr.get_avg_fps()\n    nframes = smart_nframes({}, total_frames=total_frames, video_fps=video_fps)\n    idx = np.linspace(0, total_frames - 1, num=nframes, dtype=np.int64)\n    idx = np.unique(idx)\n    video_np = vr.get_batch(idx).asnumpy()\n    video = torch.from_numpy(video_np).pin_memory()\n    video = video.permute(0, 3, 1, 2)  # Convert to TCHW format","sourceCodeStart":149,"sourceCodeEnd":185,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/srt/multimodal/processors/ernie45_vl.py#L149-L185","documentation":"Raised by ernie45_vl.smart_nframes after clamping and floor-rounding the target frame count to FRAME_FACTOR: the result fell outside [FRAME_FACTOR, total_frames]. Because floor_by_factor can drop nframes below FRAME_FACTOR (e.g. total_frames=7, factor=4, clamp gives 4 but floor of an odd count can yield 0 in degenerate cases), or the video has fewer frames than FRAME_FACTOR, no valid frame count exists.","triggerScenarios":"Calling preprocess_video on a video whose total decoded frames < FRAME_FACTOR (2); FPS-based nframes computed from a very short clip (e.g. total_video_seconds*fps < 2); nframes clamped to max_frames that is itself below factor.","commonSituations":"Very short or corrupt video files that decode to 1 frame; metadata claiming a duration the decoder doesn't deliver; custom max_frames set to 1.","solutions":["Skip or reject videos with total_frames < FRAME_FACTOR before preprocessing","Ensure max_frames >= FRAME_FACTOR and is a multiple of the frame factor","For short clips, pad or duplicate frames so total_frames >= FRAME_FACTOR"],"exampleFix":"# before\nout = processor.preprocess_video(video_list, ...)  # video decodes to 1 frame\n# after\nif n_total < FRAME_FACTOR:\n    raise SkipSample(f'video too short: {n_total} frames')\nout = processor.preprocess_video(video_list, ...)","handlingStrategy":"validation","validationCode":"total = count_frames(path)\nif total < FRAME_FACTOR:  # 2 for ernie45\n    raise SkipSample(f'video too short: {total} frames')","typeGuard":"def has_enough_frames(path: str, minimum: int = 2) -> bool:\n    return count_frames(path) >= minimum","tryCatchPattern":"try:\n    out = preprocess_video(v, ...)\nexcept ValueError as e:\n    if 'nframes should in interval' in str(e):\n        mark_video_corrupt(v); continue\n    raise","preventionTips":["Pre-scan video duration/frames before batching","Keep max_frames a multiple of FRAME_FACTOR and >= it","Drop single-frame/corrupt files at dataset build time"],"tags":["multimodal","video-preprocessing","ernie-4-5-vl","frame-sampling"],"backgroundTag":"video-frame-count-out-of-range","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T11:17:15.048Z"}