invoke-ai/InvokeAI · error · ValueError
Input videos have different frame rates; set Output FPS to r
Error message
Input videos have different frame rates; set Output FPS to retime them.
What it means
When the Output FPS field is not set, video_concat must pick a frame rate. If the probed source rates disagree (beyond rel_tol 1e-3), concatenating would silently retime clips, so it raises ValueError and asks the user to set Output FPS explicitly. Unknown (None) rates mixed with agreeing known rates are tolerated per the documented probe_video behavior.
Source
Thrown at invokeai/app/invocations/video_concat.py:196
tmp_path.unlink(missing_ok=True)
except Exception:
pass
def _estimate_transition_memory(self, width: int, height: int) -> int:
if self.transition == "cut" or self.transition_frames == 0:
return 0
buffered_frames = self.transition_frames * (2 if self.transition == "crossfade" else 1)
frame_bytes = width * height * 3
return frame_bytes * (buffered_frames + _BLEND_WORKING_FRAMES)
def _resolve_output_fps(self, source_rates: list[Optional[float]]) -> float:
if self.fps is not None:
return float(self.fps)
known_rates = [rate for rate in source_rates if rate is not None and rate > 0]
if not known_rates:
return 16.0
if any(not math.isclose(rate, known_rates[0], rel_tol=1e-3) for rate in known_rates[1:]):
raise ValueError("Input videos have different frame rates; set Output FPS to retime them.")
# An unknown rate mixed with agreeing known ones is not an error: probe_video
# deliberately reports None for metadata-poor containers (VFR flags, missing
# avg_frame_rate) whose real rate is usually the same as their neighbours'.
# Erroring here would break previously-working concat workflows over a metadata
# quirk; disagreement between *known* rates is the case that silently retimes.
return known_rates[0]
def _validate_transition_memory(self, width: int, height: int) -> None:
estimated_bytes = self._estimate_transition_memory(width, height)
if estimated_bytes > MAX_TRANSITION_MEMORY_BYTES:
estimated_mib = estimated_bytes / (1024 * 1024)
limit_mib = MAX_TRANSITION_MEMORY_BYTES / (1024 * 1024)
raise ValueError(
f"The requested transition needs an estimated {estimated_mib:.0f} MiB, "
f"which exceeds the {limit_mib:.0f} MiB transition memory budget. "
"Lower transition_frames or use lower-resolution clips."
)
View on GitHub (pinned to 0b6a024f2f)
Solutions
- Set the Output FPS field explicitly (e.g. 24 or 30) to retime all inputs to a common rate
- Normalize all inputs to the same fps before concatenating
- Accept the default only when all known source rates agree
Example fix
// before VideoConcat(videos=[clip24, clip30]) // after VideoConcat(videos=[clip24, clip30], fps=24)
Defensive patterns
Strategy: validation
Validate before calling
rates = [probe_video(p)[3] for p in paths]
known = [r for r in rates if r is not None and r > 0]
import math
if fps is None and len({r for r in known if math.isclose(r, known[0], rel_tol=1e-3)}) > 1:
fps = known[0] # must set Output FPS explicitly Try / catch
try:
output = concat.invoke(context)
except ValueError as e:
if "different frame rates" in str(e):
concat.fps = 24 # explicit common rate
output = concat.invoke(context)
else:
raise Prevention
- Always set Output FPS when mixing footage from different sources
- Normalize all clips to one fps in a preprocessing step
- Probe source fps (ffprobe avg_frame_rate) before building the graph
When it happens
Trigger: Concatenating clips with fps 24 and 30 while leaving the fps field unset in the invocation.
Common situations: Mixing phone footage (30fps) with cinematic clips (24fps); mixing screen recordings (variable/odd rates); older workflow where fps field was left at default.
Related errors
- Video URLs not found
- video_concat requires at least two input videos.
- Failed to remove image from board
- Failed to get intermediates
- Failed to update image
AI-assisted analysis of invoke-ai/InvokeAI@0b6a024f2f (2026-08-29).
Data as JSON: /api/errors/e5a7fd12d49abb12.
Report an issue: GitHub.