def build_generation_request(
request_id: str,
request: VideoGenerationRequest,
args: FastVideoArgs,
*,
served_model_name: str,
output_dir: str,
default_request: GenerationRequest | None = None,
) -> GenerationRequest:
"""Build one tracked FastVideo request using explicit-field precedence."""
validate_model_and_lora(request, args, served_model_name)
kwargs: dict[str, Any] = {}
if default_request is not None:
kwargs.update(explicit_request_updates(default_request))
body_set = request.model_fields_set
nested_set = request.video_params.model_fields_set if request.video_params is not None else set()
if "size" in body_set and request.size is not None:
width, height = request.size.split("x", 1)
kwargs["width"], kwargs["height"] = int(width), int(height)
else:
if "width" in body_set and request.width is not None:
kwargs["width"] = request.width
elif "video_params" in body_set and "width" in nested_set and request.video_params.width is not None:
kwargs["width"] = request.video_params.width
if "height" in body_set and request.height is not None:
kwargs["height"] = request.height
elif "video_params" in body_set and "height" in nested_set and request.video_params.height is not None:
kwargs["height"] = request.video_params.height
fps_explicit = ("fps" in body_set
and request.fps is not None) or ("video_params" in body_set and "fps" in nested_set
and request.video_params.fps is not None)
if fps_explicit:
fps = request.fps if "fps" in body_set else request.video_params.fps
if fps is not None:
kwargs["fps"] = fps
kwargs.setdefault("fps", 24)
frames_explicit = ("num_frames" in body_set
and request.num_frames is not None) or ("video_params" in body_set and "num_frames" in nested_set
and request.video_params.num_frames is not None)
if frames_explicit:
num_frames = request.num_frames if "num_frames" in body_set else request.video_params.num_frames
if num_frames is not None:
kwargs["num_frames"] = num_frames
elif "seconds" in body_set and request.seconds is not None:
kwargs["num_frames"] = int(request.seconds) * int(kwargs["fps"])
direct_fields = (
"seed",
"num_inference_steps",
"guidance_scale",
"guidance_scale_2",
"true_cfg_scale",
"negative_prompt",
"enable_teacache",
"max_sequence_length",
"boundary_ratio",
)
for name in direct_fields:
if name in body_set:
value = getattr(request, name)
if value is not None:
kwargs[name] = value
if "n" in body_set or "num_outputs_per_prompt" in body_set:
kwargs["num_videos_per_prompt"] = request.resolved_num_outputs
try:
_, model_family = get_preset_selection(args.model_path)
except (RuntimeError, ValueError):
model_family = None
if request.resolved_num_outputs != 1:
raise RequestAdaptationError("FastVideo serving currently supports exactly one video output per request.")
if "short_edge" in body_set and request.short_edge is not None and request.aspect_ratio is None:
raise RequestAdaptationError("short_edge requires aspect_ratio.")
_apply_aspect_ratio(kwargs, request, model_family=model_family)
_apply_reference_inputs(kwargs, request, args, model_family=model_family)
extension_fields = ("flow_shift", "sound_duration", "start_time_seconds")
for name in extension_fields:
if name in body_set and getattr(request, name) is not None:
kwargs[name] = getattr(request, name)
if "generate_sound" in body_set and request.generate_sound and model_family != "minimax_h3":
kwargs["generate_sound"] = True
if "enable_frame_interpolation" in body_set and request.enable_frame_interpolation:
kwargs["enable_frame_interpolation"] = True
for name in (
"frame_interpolation_exp",
"frame_interpolation_scale",
"frame_interpolation_model_path",
):
kwargs[name] = getattr(request, name)
if request.extra_params:
unknown_extra_params = sorted(set(request.extra_params) - set(REQUEST_BATCH_EXTRA_PASSTHROUGH_FIELDS))
if unknown_extra_params:
raise RequestAdaptationError("Unsupported extra_params fields: " + ", ".join(unknown_extra_params))
kwargs.update(request.extra_params)
width = kwargs.get("width")
height = kwargs.get("height")
if width is not None and (not isinstance(width, int) or width <= 0):
raise RequestAdaptationError(f"width must be a positive integer, got {width!r}")
if height is not None and (not isinstance(height, int) or height <= 0):
raise RequestAdaptationError(f"height must be a positive integer, got {height!r}")
if model_family == "minimax_h3":
from fastvideo.pipelines.basic.minimax_h3.packing import (
MINIMAX_H3_CANVAS_MULTIPLE,
MINIMAX_H3_MAX_PIXELS,
)
from fastvideo.pipelines.basic.minimax_h3.stages.minimax_h3_input_preparation import (
resolve_target_num_frames, )
if kwargs["fps"] != 24:
raise RequestAdaptationError(f"MiniMax-H3 requires fps=24, got {kwargs['fps']}.")
if width is None or height is None:
raise RequestAdaptationError("MiniMax-H3 requires both width and height.")
if width % MINIMAX_H3_CANVAS_MULTIPLE or height % MINIMAX_H3_CANVAS_MULTIPLE:
raise RequestAdaptationError("MiniMax-H3 width and height must be positive multiples of "
f"{MINIMAX_H3_CANVAS_MULTIPLE}, got {width}x{height}.")
if width * height > MINIMAX_H3_MAX_PIXELS:
raise RequestAdaptationError(
f"MiniMax-H3 canvas exceeds the {MINIMAX_H3_MAX_PIXELS}-pixel limit: {width}x{height}.")
try:
requested_num_frames = kwargs.get("num_frames")
aligned_num_frames = resolve_target_num_frames(requested_num_frames)
except (TypeError, ValueError) as error:
raise RequestAdaptationError(str(error)) from error
if frames_explicit and aligned_num_frames != requested_num_frames:
raise RequestAdaptationError("MiniMax-H3 num_frames must be on the causal-VAE grid (17 * n + 5); "
f"got {requested_num_frames}, next valid value is {aligned_num_frames}.")
kwargs["num_frames"] = aligned_num_frames
output_path = os.path.join(os.path.abspath(output_dir), "videos", f"{request_id}.mp4")
os.makedirs(os.path.dirname(output_path), exist_ok=True)
kwargs.update({
"output_path": output_path,
"save_video": True,
"return_frames": False,
})
generation_request = legacy_generate_call_to_request(request.prompt, None, legacy_kwargs=kwargs)
try:
# Resolve once at admission time so unsupported model-specific fields
# are a deterministic 400, rather than an asynchronous failed job.
request_to_sampling_param(generation_request, model_path=args.model_path)
except (TypeError, ValueError) as error:
raise RequestAdaptationError(str(error)) from error
return generation_request