[refactor]: move apps and docs to generate(request) and from_config

DreamVerse, FastVideo Studio, the ComfyUI node, the README, and the
inference docs call VideoGenerator.generate with nested requests and
VideoGenerator.from_config with typed configs, and read GenerationResult
attributes instead of result dict keys.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012M91wnVFmPEvJ9h39r5BH7
This commit is contained in:
Davids048
2026-10-03 02:15:04 +00:00
co-authored by Claude Opus 5.5
parent 9139c0411b
commit d6ba5ced94
12 changed files with 263 additions and 192 deletions
+5 -5
View File
@@ -372,10 +372,10 @@ generator = VideoGenerator.from_pretrained(
model_path="Wan-AI/Wan2.1-T2V-14B-Diffusers",
num_gpus=1, tp_size=1, sp_size=1,
)
result = generator.generate_video(
prompt="A cat dancing",
height=720, width=1280, num_frames=81,
)
result = generator.generate({
"prompt": "A cat dancing",
"sampling": {"height": 720, "width": 1280, "num_frames": 81},
})
```
**CLI** (`fastvideo/entrypoints/cli/`):
@@ -421,7 +421,7 @@ User: VideoGenerator.from_pretrained(model_path, **kwargs)
├─ torch.compile (if enabled)
└─ warmup_sequence_parallel_communication()
User: generator.generate_video(prompt, ...)
User: generator.generate(request)
│
├─ ForwardBatch constructed from SamplingParam + user args
└─ pipeline.forward(batch, fastvideo_args)
+31 -34
View File
@@ -37,7 +37,7 @@ You can customize generation behavior using `PipelineConfig` and
`SamplingParam`:
```python
from fastvideo import VideoGenerator, SamplingParam, PipelineConfig
from fastvideo import VideoGenerator, PipelineConfig
def main():
model_name = "Wan-AI/Wan2.1-T2V-1.3B-Diffusers"
@@ -45,43 +45,40 @@ def main():
config.vae_precision = "fp16"
# Create the generator
generator = VideoGenerator.from_pretrained(
model_name,
num_gpus=1,
dit_layerwise_offload=True, # FastVideoArgs option
pipeline_config=config
)
# Create and customize sampling parameters
sampling_param = SamplingParam.from_pretrained("Wan-AI/Wan2.1-T2V-1.3B-Diffusers")
# How many frames to generate
sampling_param.num_frames = 45
# Video resolution (width, height)
sampling_param.width = 1024
sampling_param.height = 576
# How many steps we denoise the video (higher = better quality, slower generation)
sampling_param.num_inference_steps = 30
# How strongly the video conforms to the prompt (higher = more faithful to prompt)
sampling_param.guidance_scale = 7.5
# Random seed for reproducibility
sampling_param.seed = 42 # Optional, leave unset for random results
generator = VideoGenerator.from_config({
"model_path": model_name,
"engine": {
"num_gpus": 1,
"offload": {"dit_layerwise": True}, # FastVideoArgs option
},
"pipeline": {"experimental": {"pipeline_config": config}},
})
# Generate video with custom parameters
prompt = "A beautiful sunset over a calm ocean, with gentle waves."
video = generator.generate_video(
prompt,
sampling_param=sampling_param,
output_path="my_videos/", # Controls where videos are saved
save_video=True
)
video = generator.generate({
"prompt": prompt,
"sampling": {
# How many frames to generate
"num_frames": 45,
# Video resolution (width, height)
"width": 1024,
"height": 576,
# How many steps we denoise the video (higher = better quality, slower generation)
"num_inference_steps": 30,
# How strongly the video conforms to the prompt (higher = more faithful to prompt)
"guidance_scale": 7.5,
# Random seed for reproducibility
"seed": 42, # Optional, leave unset for random results
},
"output": {
"output_path": "my_videos/", # Controls where videos are saved
"save_video": True,
},
})
# If return_frames=True, frames are available in video["frames"]
print(f"Generated {len(video['frames'])} frames")
# If return_frames=True, frames are available in video.frames
print(f"Generated {len(video.frames)} frames")
if __name__ == '__main__':
main()
+17 -14
View File
@@ -45,11 +45,13 @@ def main():
prompt = "A curious raccoon peers through a vibrant field of yellow sunflowers, its eyes wide with interest."
# Generate the video
video = generator.generate_video(
prompt,
output_path="my_videos/", # Controls where videos are saved
save_video=True
)
video = generator.generate({
"prompt": prompt,
"output": {
"output_path": "my_videos/", # Controls where videos are saved
"save_video": True,
},
})
if __name__ == '__main__':
main()
@@ -75,23 +77,24 @@ Please see the [support matrix](support_matrix.md) for the list of supported mod
You can generate a video starting from an initial image:
```python
from fastvideo import VideoGenerator, SamplingParam
from fastvideo import VideoGenerator
def main():
# Create the generator
model_name = "Wan-AI/Wan2.1-I2V-14B-480P-Diffusers"
generator = VideoGenerator.from_pretrained(model_name, num_gpus=1)
# Set up parameters with an initial image
sampling_param = SamplingParam.from_pretrained(model_name)
sampling_param.image_path = "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/astronaut.jpg"
sampling_param.num_frames = 107
# Generate video based on the image
prompt = "A photograph coming to life with gentle movement"
generator.generate_video(prompt, sampling_param=sampling_param,
output_path="my_videos/",
save_video=True)
generator.generate({
"prompt": prompt,
# Set up parameters with an initial image
"inputs": {
"image_path": "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/astronaut.jpg",
},
"sampling": {"num_frames": 107},
"output": {"output_path": "my_videos/", "save_video": True},
})
if __name__ == '__main__':
main()
+2 -2
View File
@@ -215,7 +215,7 @@ generator = VideoGenerator.from_pretrained(
)
prompt = "A curious raccoon peers through a vibrant field of yellow sunflowers."
video = generator.generate_video(prompt, output_path="output/", save_video=True)
video = generator.generate({"prompt": prompt, "output": {"output_path": "output/", "save_video": True}})
```
### Multi-GPU with FSDP
@@ -238,5 +238,5 @@ generator = VideoGenerator.from_pretrained(
)
prompt = "A majestic lion strides across the golden savanna."
video = generator.generate_video(prompt, output_path="output/", save_video=True)
video = generator.generate({"prompt": prompt, "output": {"output_path": "output/", "save_video": True}})
```
+33 -23
View File
@@ -176,7 +176,7 @@ gen = VideoGenerator.from_pretrained(
num_gpus=1,
use_fsdp_inference=False, # FSDP is incompatible with FP4 pointer path
)
gen.generate_video(prompt="A raccoon in sunflowers", save_video=True)
gen.generate(request={"prompt": "A raccoon in sunflowers", "output": {"save_video": True}})
```
#### Known Limitations
@@ -206,14 +206,20 @@ os.environ["FASTVIDEO_ATTENTION_BACKEND"] = "ATTN_QAT_INFER"
from fastvideo import VideoGenerator
from fastvideo.layers.quantization import get_quantization_config
gen = VideoGenerator.from_pretrained(
"Wan-AI/Wan2.1-T2V-1.3B-Diffusers",
num_gpus=1,
# Wan-2.1 uses the nvfp4_qat config (NVFP4 is LTX2-specific). Pass an
# instance — the bare string is not resolved on the from_pretrained path.
transformer_quant=get_quantization_config("nvfp4_qat")(),
use_fsdp_inference=False, # FSDP shards invalidate the FP4 tensor pointers
)
gen = VideoGenerator.from_config({
"model_path": "Wan-AI/Wan2.1-T2V-1.3B-Diffusers",
"engine": {
"num_gpus": 1,
"use_fsdp_inference": False, # FSDP shards invalidate the FP4 tensor pointers
},
"pipeline": {
"experimental": {
# Wan-2.1 uses the nvfp4_qat config (NVFP4 is LTX2-specific). Pass an
# instance — the bare string is not resolved under pipeline.experimental.
"transformer_quant": get_quantization_config("nvfp4_qat")(),
},
},
})
gen.generate(request={"prompt": "A raccoon in sunflowers", "output": {"save_video": True}})
```
@@ -305,12 +311,16 @@ automatically.
from fastvideo import VideoGenerator
from fastvideo.layers.quantization import get_quantization_config
gen = VideoGenerator.from_pretrained(
"Wan-AI/Wan2.1-T2V-1.3B-Diffusers",
# Pass an instance — the bare string is not resolved on the from_pretrained path.
transformer_quant=get_quantization_config("FP8")(), # per-tensor (default)
# transformer_quant=get_quantization_config("FP8")(granularity="channel"), # slower, higher accuracy
)
gen = VideoGenerator.from_config({
"model_path": "Wan-AI/Wan2.1-T2V-1.3B-Diffusers",
"pipeline": {
"experimental": {
# Pass an instance — the bare string is not resolved under pipeline.experimental.
"transformer_quant": get_quantization_config("FP8")(), # per-tensor (default)
# "transformer_quant": get_quantization_config("FP8")(granularity="channel"), # slower, higher accuracy
},
},
})
gen.generate(request={"prompt": "A raccoon in sunflowers", "output": {"save_video": True}})
```
@@ -376,10 +386,10 @@ device is unsupported. Legacy VSA, MiniMax-H3 tile-256 VSA, and the explicit
eager with one warning instead of failing mid-denoise.
```python
generator = VideoGenerator.from_pretrained(
"MiniMaxAI/MiniMax-H3",
inference_torch_compile=True, # or FASTVIDEO_INFERENCE_TORCH_COMPILE=1
)
generator = VideoGenerator.from_config({
"model_path": "MiniMaxAI/MiniMax-H3",
"engine": {"compile": {"regional": True}}, # or FASTVIDEO_INFERENCE_TORCH_COMPILE=1
})
```
In a YAML config, set `generator.engine.compile.regional: true`.
@@ -501,10 +511,10 @@ for backend in ["TORCH_SDPA", "FLASH_ATTN", "SAGE_ATTN"]:
os.environ["FASTVIDEO_ATTENTION_BACKEND"] = backend
generator = VideoGenerator.from_pretrained("your-model-id")
start_time = time.perf_counter()
generator.generate_video(
prompt="Your prompt",
seed=1024,
)
generator.generate({
"prompt": "Your prompt",
"sampling": {"seed": 1024},
})
elapsed = time.perf_counter() - start_time
print(f"{backend}: {elapsed:.2f}s")
```