[refactor]: migrate examples/scripts to typed VideoGenerator API; rename api/compat.py to api/translation.py
Move all examples/inference and scripts off the legacy
VideoGenerator.from_pretrained(model, **kwargs) +
generate_video(prompt, **kwargs) surface onto the typed
from_config(GeneratorConfig(...)) + generate(GenerationRequest(...))
convention, including the Kandinsky-5 and DreamX-World examples added
on main after the original migration. git-mv api/compat.py to
api/translation.py ('compat' implied a temporary shim; the forward
translation is its honest permanent role) and repoint all importers,
tests, and doc links.
This commit is contained in:
@@ -13,7 +13,8 @@ The base DiT uses Wan-AI/Wan2.2-TI2V-5B's VAE and google/t5gemma-9b-9b-ul2's
|
||||
encoder at inference time; neither is bundled upstream.
|
||||
|
||||
This converter takes the raw MagiHuman base DiT and emits a Diffusers-style
|
||||
directory so `VideoGenerator.from_pretrained(...)` can load it standalone:
|
||||
directory so `VideoGenerator.from_config(GeneratorConfig(model_path=...))` can
|
||||
load it standalone:
|
||||
|
||||
<output>/
|
||||
model_index.json
|
||||
|
||||
@@ -683,21 +683,23 @@ def main():
|
||||
print()
|
||||
print(" 1. Test basic generation:")
|
||||
print(" from fastvideo import VideoGenerator")
|
||||
print(f" generator = VideoGenerator.from_pretrained('{output_dir}')")
|
||||
print(" video = generator.generate_video(")
|
||||
print(" from fastvideo.api import GeneratorConfig, GenerationRequest, SamplingConfig")
|
||||
print(f" generator = VideoGenerator.from_config(GeneratorConfig(model_path='{output_dir}'))")
|
||||
print(" result = generator.generate(GenerationRequest(")
|
||||
print(" prompt='A cat playing piano',")
|
||||
print(" num_inference_steps=50")
|
||||
print(" )")
|
||||
print(" sampling=SamplingConfig(num_inference_steps=50),")
|
||||
print(" ))")
|
||||
print()
|
||||
if (output_dir / "lora" / "distilled").exists():
|
||||
print(" 2. Test distilled generation (16 steps with LoRA):")
|
||||
print(f" generator = VideoGenerator.from_pretrained('{output_dir}',")
|
||||
print(f" lora_path='{output_dir}/lora/distilled',")
|
||||
print(" lora_nickname='distilled')")
|
||||
print(" video = generator.generate_video(")
|
||||
print(" from fastvideo.api import ComponentConfig, PipelineSelection")
|
||||
print(f" generator = VideoGenerator.from_config(GeneratorConfig(model_path='{output_dir}',")
|
||||
print(f" pipeline=PipelineSelection(")
|
||||
print(f" components=ComponentConfig(lora_path='{output_dir}/lora/distilled'),")
|
||||
print(" experimental={'lora_nickname': 'distilled'})))")
|
||||
print(" result = generator.generate(GenerationRequest(")
|
||||
print(" prompt='A cat playing piano',")
|
||||
print(" num_inference_steps=16,")
|
||||
print(" guidance_scale=1.0)")
|
||||
print(" sampling=SamplingConfig(num_inference_steps=16, guidance_scale=1.0)))")
|
||||
print()
|
||||
print()
|
||||
|
||||
|
||||
@@ -18,7 +18,8 @@ Example (one-shot per variant):
|
||||
--public
|
||||
|
||||
After upload, the local directory can be deleted — the HF repo is the
|
||||
source of truth. `VideoGenerator.from_pretrained("FastVideo/...")` pulls
|
||||
source of truth.
|
||||
`VideoGenerator.from_config(GeneratorConfig(model_path="FastVideo/..."))` pulls
|
||||
shards on demand.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
@@ -97,42 +97,53 @@ def generate_with_model(
|
||||
flow_shift: Optional[float] = None,
|
||||
embedded_guidance_scale: Optional[float] = None,
|
||||
) -> str:
|
||||
"""Produce a video with VideoGenerator.from_pretrained; returns video path."""
|
||||
"""Produce a video with VideoGenerator.from_config; returns video path."""
|
||||
try:
|
||||
from fastvideo import VideoGenerator # lazy import
|
||||
from fastvideo.api import (
|
||||
ComponentConfig, EngineConfig, GenerationRequest, GeneratorConfig,
|
||||
OffloadConfig, OutputConfig, PipelineSelection, SamplingConfig,
|
||||
)
|
||||
except Exception as exc:
|
||||
raise RuntimeError(f"Failed to import fastvideo.VideoGenerator: {exc}") from exc
|
||||
|
||||
init_kwargs: Dict[str, Any] = {
|
||||
"num_gpus": 1,
|
||||
"dit_cpu_offload": True,
|
||||
"vae_cpu_offload": True,
|
||||
"text_encoder_cpu_offload": True,
|
||||
"pin_cpu_memory": True,
|
||||
}
|
||||
pipeline_kwargs: Dict[str, Any] = {}
|
||||
if lora_path:
|
||||
init_kwargs["lora_path"] = lora_path
|
||||
init_kwargs["lora_nickname"] = "extracted"
|
||||
pipeline_kwargs["components"] = ComponentConfig(lora_path=lora_path)
|
||||
pipeline_kwargs["experimental"] = {"lora_nickname": "extracted"}
|
||||
|
||||
generator = VideoGenerator.from_pretrained(model_path, **init_kwargs)
|
||||
generator = VideoGenerator.from_config(GeneratorConfig(
|
||||
model_path=model_path,
|
||||
engine=EngineConfig(
|
||||
num_gpus=1,
|
||||
offload=OffloadConfig(dit=True, vae=True, text_encoder=True, pin_cpu_memory=True),
|
||||
),
|
||||
pipeline=PipelineSelection(**pipeline_kwargs),
|
||||
))
|
||||
|
||||
gen_kwargs = {
|
||||
"height": height,
|
||||
"width": width,
|
||||
"num_frames": num_frames,
|
||||
"num_inference_steps": num_inference_steps,
|
||||
"guidance_scale": guidance_scale,
|
||||
"seed": seed,
|
||||
"output_path": output_dir,
|
||||
"output_video_name": output_name,
|
||||
"save_video": True,
|
||||
}
|
||||
extensions: Dict[str, Any] = {}
|
||||
if flow_shift is not None:
|
||||
gen_kwargs["flow_shift"] = flow_shift
|
||||
extensions["flow_shift"] = flow_shift
|
||||
if embedded_guidance_scale is not None:
|
||||
gen_kwargs["embedded_guidance_scale"] = embedded_guidance_scale
|
||||
extensions["embedded_guidance_scale"] = embedded_guidance_scale
|
||||
|
||||
result = generator.generate_video(prompt, **gen_kwargs)
|
||||
result = generator.generate(GenerationRequest(
|
||||
prompt=prompt,
|
||||
sampling=SamplingConfig(
|
||||
height=height,
|
||||
width=width,
|
||||
num_frames=num_frames,
|
||||
num_inference_steps=num_inference_steps,
|
||||
guidance_scale=guidance_scale,
|
||||
seed=seed,
|
||||
),
|
||||
output=OutputConfig(
|
||||
output_path=output_dir,
|
||||
output_video_name=output_name,
|
||||
save_video=True,
|
||||
),
|
||||
extensions=extensions,
|
||||
))
|
||||
|
||||
# best-effort cleanup of internal executors
|
||||
try:
|
||||
@@ -145,9 +156,9 @@ def generate_with_model(
|
||||
expected = Path(output_dir) / f"{output_name}.mp4"
|
||||
if expected.exists():
|
||||
return str(expected)
|
||||
# fallback: check result dict
|
||||
if isinstance(result, dict) and "video_path" in result:
|
||||
return str(result["video_path"])
|
||||
# fallback: check result video path
|
||||
if getattr(result, "video_path", None):
|
||||
return str(result.video_path)
|
||||
raise FileNotFoundError(f"Video not found at expected path: {expected}")
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user