Comfy-Org/ComfyUI · error · ValueError
Video too short: need at least 16 frames for Moonvalley
Error message
Video too short: need at least 16 frames for Moonvalley
What it means
The Moonvalley trim helper rounds the target frame count down to the nearest multiple of 16 (a hard requirement of that model's video encoder). estimated_frames = int(duration_sec * fps); target_frames = (estimated_frames // 16) * 16. When the requested duration at the source fps yields fewer than 16 frames, target_frames becomes 0 and the helper refuses to encode.
Source
Thrown at comfy_api_nodes/util/conversions.py:360
video_stream = output_container.add_stream("h264", rate=stream.average_rate)
video_stream.width = stream.width
video_stream.height = stream.height
video_stream.pix_fmt = "yuv420p"
logging.info("Added video stream: %sx%s @ %sfps", stream.width, stream.height, stream.average_rate)
elif isinstance(stream, av.AudioStream):
# Create output audio stream with same parameters
audio_stream = output_container.add_stream("aac", rate=stream.sample_rate)
audio_stream.sample_rate = stream.sample_rate
audio_stream.layout = stream.layout
logging.info("Added audio stream: %sHz, %s channels", stream.sample_rate, stream.channels)
# Calculate target frame count that's divisible by 16
fps = input_container.streams.video[0].average_rate
estimated_frames = int(duration_sec * fps)
target_frames = (estimated_frames // 16) * 16 # Round down to nearest multiple of 16
if target_frames == 0:
raise ValueError("Video too short: need at least 16 frames for Moonvalley")
frame_count = 0
audio_frame_count = 0
# Decode and re-encode video frames
if video_stream:
for frame in input_container.decode(video=0):
if frame_count >= target_frames:
break
# Re-encode frame
for packet in video_stream.encode(frame):
output_container.mux(packet)
frame_count += 1
# Flush encoder
for packet in video_stream.encode():
output_container.mux(packet)View on GitHub (pinned to 1c6d8d45b3)
Solutions
- Increase the trim duration so that duration_sec * fps >= 16 (e.g. at least 1s at 16fps, ~0.67s at 24fps).
- Verify the source clip's average_rate with av or ffprobe; low-fps sources need longer durations.
- Check that the duration value is in seconds, not milliseconds or frame counts.
- If the source clip itself is shorter than 16 frames, use a longer source video.
Example fix
// before trimmed = trim_video(video, start_time=0.0, duration=0.4) # 24fps -> 9 frames // after fps = float(video.get_dimensions() and 24) # know your source fps min_duration = math.ceil(16 / fps) trimmed = trim_video(video, start_time=0.0, duration=max(0.4, min_duration))
Defensive patterns
Strategy: validation
Validate before calling
fps = float(input_container.streams.video[0].average_rate)
if int(duration_sec * fps) < 16:
raise ValueError(f'Duration {duration_sec}s at {fps}fps gives fewer than 16 frames; need >= {16 / fps:.2f}s') Try / catch
try:
trimmed = trim_video(video, start_time, duration)
except ValueError as e:
if 'at least 16 frames' in str(e):
duration = max(duration, math.ceil(16 / fps))
trimmed = trim_video(video, start_time, duration)
else:
raise Prevention
- Clamp duration inputs to >= ceil(16 / source_fps) seconds in node UIs.
- Check average_rate of the source before configuring trim parameters.
- Reject duration <= 0 at input validation time.
When it happens
Trigger: Calling the trim path in comfy_api_nodes/util/conversions.py with a source whose fps * requested duration < 16 frames: e.g. a 5 fps clip trimmed to ~1s (5 frames), a 24 fps clip trimmed to 0.5s (12 frames), or a duration of 0.
Common situations: Trim controls (start + duration) on a Moonvalley image-to-video workflow set too short; a low-fps GIF or screen-recording source; duration accidentally left at 0 or computed from a wrong time unit (milliseconds vs seconds).
Related errors
- resize produced no frames (start_time={start_time}, duration
- ar_video sampler requires 5-D video latents [B,C,T,H,W], got
- unknown merge strategy {self.merge_strategy}
- SeedVR2 patch input temporal size must satisfy T % {t} == 1,
- SeedVR2 expected {name} to be 5-D native latent, got shape {
AI-assisted analysis of Comfy-Org/ComfyUI@1c6d8d45b3 (2026-08-14).
Data as JSON: /api/errors/047af15dc5045812.
Report an issue: GitHub.