Comfy-Org/ComfyUI · error · ValueError

Input video frame rate ({fps:.2f} fps) exceeds Aleph2's maxi

Error message

Input video frame rate ({fps:.2f} fps) exceeds Aleph2's maximum of 30 fps.

What it means

Raised by the Runway Aleph2 video-to-video node when the input video's frame rate, read via video.get_frame_rate(), exceeds 30 fps (with a 0.01 tolerance). If the frame rate cannot be read the check is skipped, so it only fires when fps is determinable and above the limit. It fires before any upload happens.

Source

Thrown at comfy_api_nodes/nodes_runway.py:776

        prompt: str,
        video: Input.Video,
        seed: int,
        public_figure_threshold: str = "low",
        keyframes: RunwayAleph2KeyframeChain | None = None,
        prompt_images: RunwayAleph2PromptImageChain | None = None,
    ) -> IO.NodeOutput:
        validate_string(prompt, min_length=1, max_length=1000)
        validate_video_duration(
            video,
            min_duration=2.0,
            max_duration=30.0,
        )
        try:
            fps = float(video.get_frame_rate())
        except Exception:
            fps = None
        if fps is not None and fps > 30.0 + 0.01:
            raise ValueError(f"Input video frame rate ({fps:.2f} fps) exceeds Aleph2's maximum of 30 fps.")

        if (keyframes and keyframes.items) and (prompt_images and prompt_images.items):
            raise ValueError("Aleph2 accepts either keyframes or prompt images, not both.")

        video_duration: float | None = None
        try:
            video_duration = video.get_duration()
        except Exception:
            video_duration = None

        def _check_seconds(value: float, label: str) -> None:
            if video_duration is not None and value > video_duration + 0.0001:
                raise ValueError(f"{label} {value:.2f}s exceeds the input video duration ({video_duration:.2f}s).")

        video_url = await upload_video_to_comfyapi(cls, video)

        keyframe_models: list[RunwayAleph2KeyframeSeconds | RunwayAleph2KeyframeAt] = []
        if keyframes is not None:

View on GitHub (pinned to 1c6d8d45b3)

Solutions

  1. Re-encode or resample the video to 30 fps or lower before the node (e.g. ffmpeg -r 30)
  2. Use a video frame-rate conversion node upstream in the workflow
  3. If the source is genuinely high-fps, decimate frames rather than duplicating to keep duration correct

Example fix

# before
video_60fps = load_video("clip.mp4")  # 60 fps
aleph2(prompt, video_60fps, ...)

# after
# shell: ffmpeg -i clip.mp4 -r 30 clip_30fps.mp4
video_30fps = load_video("clip_30fps.mp4")
aleph2(prompt, video_30fps, ...)
Defensive patterns

Strategy: validation

Validate before calling

try:
    fps = float(video.get_frame_rate())
except Exception:
    fps = None
if fps is not None and fps > 30.01:
    raise ValueError(f"Resample {fps:.2f} fps video to <=30 fps before Aleph2")

Type guard

def is_aleph2_safe_fps(video) -> bool:
    try:
        return float(video.get_frame_rate()) <= 30.01
    except Exception:
        return True  # check is skipped when fps is unreadable

Try / catch

try:
    await aleph2_execute(...)
except ValueError as e:
    if "frame rate" in str(e):
        video = reencode_at_30fps(video)  # then retry
    else:
        raise

Prevention

When it happens

Trigger: Passing a video with fps > 30.01 (e.g. 60 fps gameplay/screen capture, 50 fps PAL footage) to the Aleph2 node; video.get_frame_rate() must succeed for the check to run.

Common situations: Feeding 60fps phone footage or high-framerate screen recordings; mixing 60fps sources into a workflow built for cinematic 24/30fps material.

Related errors


AI-assisted analysis of Comfy-Org/ComfyUI@1c6d8d45b3 (2026-08-14). Data as JSON: /api/errors/f9b9ae9b02377ea1. Report an issue: GitHub.