diff --git a/README.md b/README.md index 583c858bd..74af69025 100644 --- a/README.md +++ b/README.md @@ -93,7 +93,6 @@ def main(): # Generate the video video = generator.generate_video( prompt, - return_frames=True, # Also return frames from this call (defaults to False) output_path="my_videos/", # Controls where videos are saved save_video=True ) diff --git a/docs/getting_started/quick_start.md b/docs/getting_started/quick_start.md index 59dbe75d0..9b754f58a 100644 --- a/docs/getting_started/quick_start.md +++ b/docs/getting_started/quick_start.md @@ -41,7 +41,6 @@ def main(): # Generate the video video = generator.generate_video( prompt, - return_frames=True, # Also return frames from this call (defaults to False) output_path="my_videos/", # Controls where videos are saved save_video=True ) diff --git a/docs/inference/configuration.md b/docs/inference/configuration.md index ac33d0300..e559ff000 100644 --- a/docs/inference/configuration.md +++ b/docs/inference/configuration.md @@ -61,12 +61,11 @@ def main(): prompt, sampling_param=sampling_param, output_path="my_videos/", # Controls where videos are saved - return_frames=True, # Also return frames from this call (defaults to False) save_video=True ) - # If return_frames=True, video contains the generated frames as a NumPy array - print(f"Generated {len(video)} frames") + # If return_frames=True, frames are available in video["frames"] + print(f"Generated {len(video['frames'])} frames") if __name__ == '__main__': main() @@ -76,6 +75,8 @@ if __name__ == '__main__': The CLI supports `--config` with JSON or YAML. Command-line arguments override config file values. +By default, `fastvideo generate` uses `return_frames=false` unless you set +`--return-frames` (or `return_frames: true` in config). ```bash fastvideo generate --config config.yaml diff --git a/docs/inference/inference_quick_start.md b/docs/inference/inference_quick_start.md index 6d5d10791..a5e0db2f9 100644 --- a/docs/inference/inference_quick_start.md +++ b/docs/inference/inference_quick_start.md @@ -44,7 +44,6 @@ def main(): # Generate the video video = generator.generate_video( prompt, - return_frames=True, # Also return frames from this call (defaults to False) output_path="my_videos/", # Controls where videos are saved save_video=True ) diff --git a/examples/inference/gradio/serving/ray_serve_backend.py b/examples/inference/gradio/serving/ray_serve_backend.py index 3e549f9db..495aec3f6 100644 --- a/examples/inference/gradio/serving/ray_serve_backend.py +++ b/examples/inference/gradio/serving/ray_serve_backend.py @@ -168,7 +168,7 @@ def prepare_sampling_params(video_request: VideoGenerationRequest, default_param params.height = video_request.height params.width = video_request.width params.save_video = False - params.return_frames = False + params.return_frames = True return params @@ -229,7 +229,7 @@ class BaseModelDeployment: sampling_param=params, image_path=image_path, save_video=False, - return_frames=False, + return_frames=True, ) inference_time = time.time() - inference_start_time diff --git a/fastvideo/configs/sample/base.py b/fastvideo/configs/sample/base.py index 2728899fb..cb7b64f86 100644 --- a/fastvideo/configs/sample/base.py +++ b/fastvideo/configs/sample/base.py @@ -75,7 +75,7 @@ class SamplingParam: # Misc save_video: bool = True - return_frames: bool = False + return_frames: bool = True return_trajectory_latents: bool = False # returns all latents for each timestep return_trajectory_decoded: bool = False # returns decoded latents for each timestep @@ -218,7 +218,7 @@ class SamplingParam: parser.add_argument( "--return-frames", action="store_true", - default=SamplingParam.return_frames, + default=False, help="Whether to return the raw frames", ) parser.add_argument( diff --git a/fastvideo/entrypoints/cli/generate.py b/fastvideo/entrypoints/cli/generate.py index 67058f76d..954f2d99c 100644 --- a/fastvideo/entrypoints/cli/generate.py +++ b/fastvideo/entrypoints/cli/generate.py @@ -80,6 +80,7 @@ class GenerateSubcommand(CLISubcommand): k: v for k, v in merged_args.items() if k in self.generation_arg_names } + generation_args.setdefault("return_frames", False) model_path = init_args.pop('model_path') prompt = generation_args.pop('prompt', None) diff --git a/fastvideo/entrypoints/video_generator.py b/fastvideo/entrypoints/video_generator.py index d0cc89aac..8aee46e1a 100644 --- a/fastvideo/entrypoints/video_generator.py +++ b/fastvideo/entrypoints/video_generator.py @@ -125,7 +125,7 @@ class VideoGenerator: grid_sizes: tuple[int, int, int] | list[int] | torch.Tensor | None = None, **kwargs, - ) -> dict[str, Any] | list[np.ndarray] | list[dict[str, Any]]: + ) -> dict[str, Any] | list[dict[str, Any]]: """ Generate a video based on the given prompt. @@ -135,7 +135,7 @@ class VideoGenerator: output_path: Path to save the video (overrides the one in fastvideo_args) prompt_path: Path to prompt file save_video: Whether to save the video to disk - return_frames: Whether to return the raw frames + return_frames: Whether to include raw frames in the result dict num_inference_steps: Number of denoising steps (overrides fastvideo_args) guidance_scale: Classifier-free guidance scale (overrides fastvideo_args) num_frames: Number of frames to generate (overrides fastvideo_args) @@ -147,7 +147,8 @@ class VideoGenerator: callback_steps: Number of steps between each callback Returns: - Either the output dictionary, list of frames, or list of results for batch processing + A metadata dictionary for single-prompt generation, or a list of + metadata dictionaries for prompt-file batch generation. """ # Handle batch processing from text file if sampling_param is None: @@ -194,9 +195,8 @@ class VideoGenerator: **kwargs) # Add prompt info to result - if isinstance(result, dict): - result["prompt_index"] = i - result["prompt"] = batch_prompt + result["prompt_index"] = i + result["prompt"] = batch_prompt results.append(result) logger.info("Successfully generated video for prompt %d", @@ -306,7 +306,7 @@ class VideoGenerator: prompt: str, sampling_param: SamplingParam | None = None, **kwargs, - ) -> dict[str, Any] | list[np.ndarray]: + ) -> dict[str, Any]: """Internal method for single video generation""" # Create a copy of inference args to avoid modifying the original fastvideo_args = self.fastvideo_args @@ -475,21 +475,22 @@ class VideoGenerator: logger.warning( "Audio mux failed; saved video without audio.") - if batch.return_frames: - return frames - else: - return { - "samples": samples, - "frames": frames, - "audio": output_batch.extra.get("audio"), - "prompts": prompt, - "size": (target_height, target_width, batch.num_frames), - "generation_time": gen_time, - "logging_info": logging_info, - "trajectory": output_batch.trajectory_latents, - "trajectory_timesteps": output_batch.trajectory_timesteps, - "trajectory_decoded": output_batch.trajectory_decoded, - } + result: dict[str, Any] = { + "prompts": prompt, + "samples": samples if batch.return_frames else None, + "frames": frames if batch.return_frames else None, + "audio": + output_batch.extra.get("audio") if batch.return_frames else None, + "size": (target_height, target_width, batch.num_frames), + "generation_time": gen_time, + "logging_info": logging_info, + "trajectory": output_batch.trajectory_latents, + "trajectory_timesteps": output_batch.trajectory_timesteps, + "trajectory_decoded": output_batch.trajectory_decoded, + "video_path": output_path if batch.save_video else None, + } + + return result @staticmethod def _mux_audio( diff --git a/tests/local_tests/pipelines/test_gamecraft_pipeline_parity.py b/tests/local_tests/pipelines/test_gamecraft_pipeline_parity.py index 3fb364254..c6cd2e29d 100644 --- a/tests/local_tests/pipelines/test_gamecraft_pipeline_parity.py +++ b/tests/local_tests/pipelines/test_gamecraft_pipeline_parity.py @@ -340,9 +340,8 @@ def test_gamecraft_pipeline_latent_parity(): camera_states=plucker_embedding, ) - fastvideo_latents = result.get("latents") - if fastvideo_latents is None: - fastvideo_latents = result.get("samples") + + fastvideo_latents = result.get("samples") _log_tensor_stats("FastVideo latents", fastvideo_latents)