[docs] refresh consumer guide recipes and deployment
This commit is contained in:
@@ -54,6 +54,7 @@ jobs:
|
||||
run: uv pip install --system -r requirements-mkdocs.txt
|
||||
|
||||
- name: Setup Pages
|
||||
id: pages
|
||||
uses: actions/configure-pages@v4
|
||||
|
||||
- name: Build documentation
|
||||
@@ -65,7 +66,7 @@ jobs:
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20'
|
||||
node-version: '24'
|
||||
|
||||
- name: Enable pnpm
|
||||
run: corepack enable
|
||||
@@ -76,13 +77,19 @@ jobs:
|
||||
|
||||
- name: Build config generator
|
||||
working-directory: consumer-guide
|
||||
run: NEXT_BASE_PATH=/config-generator pnpm build
|
||||
env:
|
||||
NEXT_BASE_PATH: ${{ steps.pages.outputs.base_path }}/config-generator
|
||||
NEXT_TELEMETRY_DISABLED: '1'
|
||||
run: pnpm build
|
||||
|
||||
- name: Copy config generator into docs site
|
||||
run: |
|
||||
mkdir -p site/config-generator
|
||||
cp -R consumer-guide/out/. site/config-generator/
|
||||
|
||||
- name: Verify config generator asset paths
|
||||
run: grep -Fq "${{ steps.pages.outputs.base_path }}/config-generator/_next/" site/config-generator/index.html
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-pages-artifact@v3
|
||||
with:
|
||||
|
||||
+33
-54
@@ -1,12 +1,15 @@
|
||||
# FastVideo Config Generator
|
||||
|
||||
A standalone Next.js app that helps users generate FastVideo inference commands.
|
||||
Deployed under `/config-generator` on the FastVideo docs site.
|
||||
A standalone Next.js app that turns maintained FastVideo inference recipes into
|
||||
executable YAML or Python. The docs build exports it beneath the GitHub Pages
|
||||
base path at `config-generator/`.
|
||||
|
||||
Two pages:
|
||||
Two pages are available:
|
||||
|
||||
- **Quick Start** (`/config-generator/`) — pick a task + hardware + output mode, get a ready-to-run command.
|
||||
- **Advanced Tuning** (`/config-generator/tuning/`) — tune generation parameters and see the real benchmarked time.
|
||||
- **Quick Start** (`/config-generator/`) — choose a task, model profile, and GPU
|
||||
count.
|
||||
- **Advanced Tuning** (`/config-generator/tuning/`) — start from an exact model
|
||||
recipe and adjust supported configuration fields.
|
||||
|
||||
## Run locally
|
||||
|
||||
@@ -15,65 +18,41 @@ pnpm install
|
||||
pnpm dev
|
||||
```
|
||||
|
||||
Open **http://localhost:3003/config-generator/** (the app is served under the `/config-generator` base path).
|
||||
Open <http://localhost:3003/config-generator/>.
|
||||
|
||||
## Build
|
||||
|
||||
```bash
|
||||
pnpm build # static export to ./out
|
||||
pnpm build
|
||||
```
|
||||
|
||||
## Data files
|
||||
The build first runs `scripts/validate-data.mjs`, then writes a static export to
|
||||
`out/`.
|
||||
|
||||
All data lives in `data/`. The `.tsx` pages contain no hardcoded model or benchmark
|
||||
data — they read these JSON files:
|
||||
## Recipe data
|
||||
|
||||
- **`data/quickstart.json`** — drives the Quick Start page: curated product `profiles`,
|
||||
plus task / tier / hardware option lists and defaults.
|
||||
- **`data/tuning.json`** — drives the Advanced Tuning page: every benchmark `run` is one
|
||||
real measured configuration, plus model / workload / gpu / preset option lists and defaults.
|
||||
`data/tuning.json` is the app's recipe source. Its `source` block pins the exact
|
||||
FastVideo revision and repository paths used to transcribe model defaults,
|
||||
pipeline settings, examples, and verified attention compatibility.
|
||||
|
||||
Both are the machine-readable record of the RTX 5090 / 4090 inference benchmarks
|
||||
(`5090_inference.xlsx`, `4090_inference.xlsx`). A configuration is included only when the
|
||||
benchmark actually recorded a generation time — **nothing is estimated**.
|
||||
`data/quickstart.json` contains only the curated task/profile choices and engine
|
||||
offload settings. Each profile references a model from `tuning.json`; the build
|
||||
fails on missing models, task mismatches, duplicate profiles, unknown attention
|
||||
backends, or unsupported performance fields.
|
||||
|
||||
## Adding a configuration
|
||||
The guide intentionally publishes no latency, VRAM, RAM, or speedup claims.
|
||||
Add those only when a reproducible benchmark record includes the FastVideo and
|
||||
model revisions, GPU type/count, complete resolved recipe, software environment,
|
||||
prompt/seed, warmup/sample protocol, latency statistic, and peak memory.
|
||||
|
||||
The pages are data-driven — to add or change a configuration, edit the JSON, not the `.tsx`:
|
||||
## Updating a recipe
|
||||
|
||||
- **Quick Start** — add an entry to `profiles[]` in `data/quickstart.json`. If it
|
||||
introduces a new task / hardware / tier, also add it to the matching option list.
|
||||
- **Advanced Tuning** — add an entry to `runs[]` in `data/tuning.json`. If it
|
||||
introduces a new model / workload / gpu / preset, also add it to the matching list.
|
||||
1. Check the current registry, model-family preset, pipeline config, maintained
|
||||
example, and support matrix.
|
||||
2. Update the model entry in `data/tuning.json` and advance
|
||||
`source.fastvideoCommit` to the inspected revision.
|
||||
3. Update `data/quickstart.json` only if the curated profile selection changes.
|
||||
4. Run `pnpm build`.
|
||||
|
||||
The only thing not in JSON: a task's `icon` must be one of the lucide-react icons
|
||||
imported in `basic_page.tsx` (`Film`, `Image`, `Sparkles`, `Gamepad2`). A new icon
|
||||
needs a small `.tsx` edit.
|
||||
|
||||
## Quick Start page logic
|
||||
|
||||
- Matches the user's selection (**task + tier + gpu + vram**) against `quickstart.json`
|
||||
`profiles[]`. One profile per combination.
|
||||
- Tier rule: **Quick Generate** = fastest small/distilled model; **High Quality** = largest
|
||||
model. Prefer FastVideo-owned models; fall back to other models. Both must have a passing
|
||||
benchmark.
|
||||
- If no profile matches, the combination shows "Not suitable" — no command is generated.
|
||||
- All displayed numbers (time, VRAM) come straight from the benchmark.
|
||||
|
||||
## Advanced Tuning page logic
|
||||
|
||||
- The **Model** dropdown is filtered by **Workload Type + GPU**: it only lists models with a
|
||||
passing benchmark for that combination. Models that ran out of memory on a GPU do not
|
||||
appear for it.
|
||||
- **Est. Time** is a real measured generation time, looked up by model + GPU + attention
|
||||
backend — there is no formula. Selecting a model snaps resolution / frames / steps /
|
||||
attention to its benchmarked values; tuning them away flags the time with `⚠`.
|
||||
- Top metrics — Video Length (`frames/fps`), Total Pixels (`h*w*frames`), Latent Tokens
|
||||
(`((frames-1)/4+1)*(h/8)*(w/8)`) — are deterministic arithmetic on the chosen config.
|
||||
- The generated Python command maps each control to a real FastVideo API field
|
||||
(`VideoGenerator.from_pretrained` kwargs, `SamplingParam` attributes).
|
||||
|
||||
## Notes
|
||||
|
||||
This app is independent from the main FastVideo Python package. Run all commands from
|
||||
this `consumer-guide/` directory.
|
||||
The UI reads the JSON directly; model defaults do not belong in the `.tsx`
|
||||
components.
|
||||
|
||||
+159
-264
@@ -1,35 +1,26 @@
|
||||
"use client"
|
||||
|
||||
import { useEffect, useState, useMemo } from "react"
|
||||
import { Monitor, Cpu, HardDrive, Layers, Info, Copy, Check, Film, Image, Sparkles, Gamepad2 } from "lucide-react"
|
||||
import { Layers, Copy, Check, Film, Image, Sparkles, Gamepad2 } from "lucide-react"
|
||||
import quickstartData from "@/data/quickstart.json"
|
||||
import tuningData from "@/data/tuning.json"
|
||||
|
||||
type IconName = "Film" | "Image" | "Sparkles" | "Gamepad2"
|
||||
|
||||
interface Config {
|
||||
model: string
|
||||
modelShort: string
|
||||
attn: string
|
||||
h: number
|
||||
w: number
|
||||
frames: number
|
||||
steps: number
|
||||
cfg: number
|
||||
vramMin: number
|
||||
ramMin: number
|
||||
timeSec: number
|
||||
firstRunSec?: number
|
||||
vram: string
|
||||
offload: boolean
|
||||
ditCpuOffload?: boolean
|
||||
ditLayerwiseOffload?: boolean
|
||||
vaeCpuOffload?: boolean
|
||||
textEncoderCpuOffload?: boolean
|
||||
pinCpuMemory?: boolean
|
||||
useFsdpInference?: boolean
|
||||
fps?: number
|
||||
keyboardDim?: number
|
||||
extra?: string
|
||||
interface Recipe {
|
||||
height: number
|
||||
width: number
|
||||
numFrames: number
|
||||
fps: number
|
||||
numInferenceSteps: number
|
||||
guidanceScale: number
|
||||
guidanceScale2: number | null
|
||||
embeddedCfgScale: number
|
||||
boundaryRatio: number | null
|
||||
dmdDenoisingSteps: number[] | null
|
||||
attentionBackends: string[]
|
||||
defaultAttentionBackend: string
|
||||
vsaSparsity: number
|
||||
}
|
||||
|
||||
interface TaskOption {
|
||||
@@ -39,11 +30,13 @@ interface TaskOption {
|
||||
icon: string
|
||||
}
|
||||
|
||||
interface HardwareOption {
|
||||
interface ModelOption {
|
||||
id: string
|
||||
label: string
|
||||
defaultVramGb: number
|
||||
vramOptionsGb: number[]
|
||||
name: string
|
||||
workload: string
|
||||
keyboardDim?: number
|
||||
usesMouse?: boolean
|
||||
recipe: Recipe
|
||||
}
|
||||
|
||||
interface TierOption {
|
||||
@@ -53,45 +46,25 @@ interface TierOption {
|
||||
badge?: string
|
||||
}
|
||||
|
||||
interface Profile extends Config {
|
||||
gpu: string
|
||||
vramGb: number
|
||||
interface Profile {
|
||||
task: string
|
||||
tier: string
|
||||
status: "available"
|
||||
model: string
|
||||
ditCpuOffload: boolean
|
||||
ditLayerwiseOffload: boolean
|
||||
vaeCpuOffload: boolean
|
||||
textEncoderCpuOffload: boolean
|
||||
imageEncoderCpuOffload: boolean
|
||||
pinCpuMemory: boolean
|
||||
useFsdpInference: boolean
|
||||
}
|
||||
|
||||
interface QuickstartDefaults {
|
||||
task: string
|
||||
tier: string
|
||||
gpu: string
|
||||
ramGb: number
|
||||
numGpus: number
|
||||
}
|
||||
|
||||
function formatTime(sec: number): string {
|
||||
if (sec < 90) return `~${Math.round(sec)} s`
|
||||
return `~${Math.round(sec / 60)} min`
|
||||
}
|
||||
|
||||
function InfoTip({ content }: { content: string }) {
|
||||
const [show, setShow] = useState(false)
|
||||
return (
|
||||
<span
|
||||
className="relative inline-flex"
|
||||
onMouseEnter={() => setShow(true)}
|
||||
onMouseLeave={() => setShow(false)}
|
||||
>
|
||||
<Info className="h-3 w-3 cursor-help" />
|
||||
{show && (
|
||||
<span className="absolute bottom-full left-0 z-50 mb-1.5 w-56 rounded-lg border border-border bg-white p-2.5 text-left text-xs font-normal leading-relaxed text-muted-foreground shadow-xl">
|
||||
{content}
|
||||
</span>
|
||||
)}
|
||||
</span>
|
||||
)
|
||||
}
|
||||
|
||||
const ICONS: Record<IconName, typeof Film> = {
|
||||
Film,
|
||||
Image,
|
||||
@@ -100,125 +73,75 @@ const ICONS: Record<IconName, typeof Film> = {
|
||||
}
|
||||
|
||||
const DEFAULTS = quickstartData.defaults as QuickstartDefaults
|
||||
const RAM_OPTIONS = quickstartData.ramOptionsGb as number[]
|
||||
const GPU_COUNT_OPTIONS = quickstartData.gpuCountOptions as number[]
|
||||
const HARDWARE = quickstartData.hardware as HardwareOption[]
|
||||
const HARDWARE_BY_ID = Object.fromEntries(HARDWARE.map((hardware) => [hardware.id, hardware])) as Record<string, HardwareOption>
|
||||
const PROFILES = quickstartData.profiles as Profile[]
|
||||
const TASKS = quickstartData.tasks as TaskOption[]
|
||||
const TIERS = quickstartData.tiers as TierOption[]
|
||||
const MODELS = tuningData.models as ModelOption[]
|
||||
const MODEL_BY_ID = Object.fromEntries(MODELS.map((model) => [model.id, model])) as Record<string, ModelOption>
|
||||
|
||||
function getProfile(task: string, tier: string, gpu: string, vramGb: number): Profile | undefined {
|
||||
return PROFILES.find((profile) =>
|
||||
profile.task === task &&
|
||||
profile.tier === tier &&
|
||||
profile.gpu === gpu &&
|
||||
profile.vramGb === vramGb
|
||||
)
|
||||
function getProfile(task: string, tier: string): Profile | undefined {
|
||||
return PROFILES.find((profile) => profile.task === task && profile.tier === tier)
|
||||
}
|
||||
|
||||
export default function FastVideoConfigSelector() {
|
||||
const [task, setTask] = useState(DEFAULTS.task)
|
||||
const [tier, setTier] = useState(DEFAULTS.tier)
|
||||
const [gpu, setGpu] = useState(DEFAULTS.gpu)
|
||||
const [vram, setVram] = useState(HARDWARE_BY_ID[DEFAULTS.gpu]?.defaultVramGb ?? HARDWARE[0]?.defaultVramGb ?? 0)
|
||||
const [ram, setRam] = useState(DEFAULTS.ramGb)
|
||||
const [ngpu, setNgpu] = useState(DEFAULTS.numGpus)
|
||||
const [copied, setCopied] = useState(false)
|
||||
|
||||
const hardware = HARDWARE_BY_ID[gpu] ?? HARDWARE[0]
|
||||
const config = getProfile(task, tier, gpu, vram)
|
||||
|
||||
useEffect(() => {
|
||||
const selectedHardware = HARDWARE_BY_ID[gpu]
|
||||
if (!selectedHardware) return
|
||||
const options = selectedHardware.vramOptionsGb
|
||||
if (!options.includes(vram)) {
|
||||
setVram(selectedHardware.defaultVramGb)
|
||||
}
|
||||
}, [gpu, vram])
|
||||
const profile = getProfile(task, tier)
|
||||
const selectedModel = profile ? MODEL_BY_ID[profile.model] : undefined
|
||||
const config = profile && selectedModel ? { ...profile, ...selectedModel.recipe, ...selectedModel } : undefined
|
||||
|
||||
// Report content height to the parent docs page so the embedding iframe can
|
||||
// auto-resize — same mechanism as the Advanced Tuning guide.
|
||||
useEffect(() => {
|
||||
if (typeof window === "undefined" || window.parent === window) return
|
||||
const root = document.getElementById("config-generator-root")
|
||||
if (!root) return
|
||||
|
||||
let frame = 0
|
||||
const timers: number[] = []
|
||||
|
||||
const sendHeight = () => {
|
||||
window.cancelAnimationFrame(frame)
|
||||
frame = window.requestAnimationFrame(() => {
|
||||
const height = Math.max(
|
||||
document.body.scrollHeight,
|
||||
document.body.offsetHeight,
|
||||
document.documentElement.scrollHeight,
|
||||
document.documentElement.offsetHeight,
|
||||
window.parent.postMessage(
|
||||
{ type: "fastvideo-config-generator:resize", height: Math.ceil(root.getBoundingClientRect().height) },
|
||||
window.location.origin,
|
||||
)
|
||||
window.parent.postMessage({ type: "quick-start-guide-height", height }, "*")
|
||||
})
|
||||
}
|
||||
|
||||
sendHeight()
|
||||
|
||||
const ro = new ResizeObserver(sendHeight)
|
||||
ro.observe(document.documentElement)
|
||||
ro.observe(document.body)
|
||||
|
||||
const mo = new MutationObserver(sendHeight)
|
||||
mo.observe(document.documentElement, {
|
||||
attributes: true,
|
||||
childList: true,
|
||||
characterData: true,
|
||||
subtree: true,
|
||||
})
|
||||
|
||||
window.addEventListener("load", sendHeight)
|
||||
window.addEventListener("resize", sendHeight)
|
||||
|
||||
for (const delay of [100, 300, 1000]) {
|
||||
timers.push(window.setTimeout(sendHeight, delay))
|
||||
}
|
||||
ro.observe(root)
|
||||
sendHeight()
|
||||
|
||||
return () => {
|
||||
window.cancelAnimationFrame(frame)
|
||||
timers.forEach((timer) => window.clearTimeout(timer))
|
||||
window.removeEventListener("load", sendHeight)
|
||||
window.removeEventListener("resize", sendHeight)
|
||||
mo.disconnect()
|
||||
ro.disconnect()
|
||||
}
|
||||
}, [])
|
||||
|
||||
const warning = useMemo(() => {
|
||||
if (!config) {
|
||||
return null
|
||||
}
|
||||
if (vram < config.vramMin) {
|
||||
return `This mode requires ${config.vramMin} GB VRAM. Your selection is ${vram} GB — consider switching to Quick Try.`
|
||||
}
|
||||
if (ram < config.ramMin) {
|
||||
return `This mode requires ${config.ramMin} GB RAM. Your selection is ${ram} GB.`
|
||||
}
|
||||
return null
|
||||
}, [vram, ram, config])
|
||||
|
||||
const command = useMemo(() => {
|
||||
if (!config) return ""
|
||||
|
||||
const fps = config.fps ?? 24
|
||||
const workloadType = task === "ti2v" ? "i2v" : task
|
||||
const pythonBoolean = (value: boolean) => value ? "True" : "False"
|
||||
const presetOverrideEntries = [
|
||||
task === "game" ? null : `["embedded_cfg_scale", ${config.embeddedCfgScale}]`,
|
||||
config.dmdDenoisingSteps === null
|
||||
? null
|
||||
: `["dmd_denoising_steps", [${config.dmdDenoisingSteps.join(", ")}]]`,
|
||||
].filter((entry): entry is string => Boolean(entry))
|
||||
|
||||
if (task === "game") {
|
||||
const offloadKwargs = [
|
||||
config.ditCpuOffload ? " dit_cpu_offload=True," : null,
|
||||
config.ditLayerwiseOffload ? " dit_layerwise_offload=True," : null,
|
||||
config.vaeCpuOffload ? " vae_cpu_offload=True," : null,
|
||||
config.textEncoderCpuOffload ? " text_encoder_cpu_offload=True," : null,
|
||||
config.pinCpuMemory ? " pin_cpu_memory=True," : null,
|
||||
config.useFsdpInference ? " use_fsdp_inference=True," : null,
|
||||
].filter((line): line is string => Boolean(line))
|
||||
const keyboardDim = config.keyboardDim ?? 4
|
||||
const inputLines = [
|
||||
' "image_path": "./input.png",',
|
||||
config.usesMouse === false ? null : ' "mouse_cond": actions["mouse"].unsqueeze(0),',
|
||||
' "keyboard_cond": actions["keyboard"].unsqueeze(0),',
|
||||
' "grid_sizes": grid_sizes,',
|
||||
].filter((line): line is string => Boolean(line))
|
||||
return [
|
||||
"# Game control uses the Python API because mouse/keyboard",
|
||||
"# conditions are tensors, not simple CLI fields.",
|
||||
@@ -231,46 +154,63 @@ export default function FastVideoConfigSelector() {
|
||||
"import os",
|
||||
"import torch",
|
||||
"from fastvideo import VideoGenerator",
|
||||
"from fastvideo.models.dits.matrixgame.utils import create_action_presets",
|
||||
"from fastvideo.models.dits.matrixgame2.utils import create_action_presets",
|
||||
"",
|
||||
`os.environ["FASTVIDEO_ATTENTION_BACKEND"] = "${config.attn}"`,
|
||||
`os.environ["FASTVIDEO_ATTENTION_BACKEND"] = "${config.defaultAttentionBackend}"`,
|
||||
"",
|
||||
"generator = VideoGenerator.from_pretrained(",
|
||||
` "${config.model}",`,
|
||||
` num_gpus=${ngpu},`,
|
||||
...offloadKwargs,
|
||||
")",
|
||||
"generator = VideoGenerator.from_config({",
|
||||
` "model_path": "${config.model}",`,
|
||||
" \"engine\": {",
|
||||
` "num_gpus": ${ngpu},`,
|
||||
` "use_fsdp_inference": ${pythonBoolean(config.useFsdpInference)},`,
|
||||
" \"offload\": {",
|
||||
` "dit": ${pythonBoolean(config.ditCpuOffload)},`,
|
||||
` "dit_layerwise": ${pythonBoolean(config.ditLayerwiseOffload)},`,
|
||||
` "text_encoder": ${pythonBoolean(config.textEncoderCpuOffload)},`,
|
||||
` "image_encoder": ${pythonBoolean(config.imageEncoderCpuOffload)},`,
|
||||
` "vae": ${pythonBoolean(config.vaeCpuOffload)},`,
|
||||
` "pin_cpu_memory": ${pythonBoolean(config.pinCpuMemory)},`,
|
||||
" },",
|
||||
" },",
|
||||
" \"pipeline\": {",
|
||||
" \"workload_type\": \"i2v\",",
|
||||
" \"preset_overrides\": dict([",
|
||||
...presetOverrideEntries.map((entry) => ` ${entry},`),
|
||||
" ]),",
|
||||
" },",
|
||||
"})",
|
||||
"",
|
||||
`num_frames = ${config.frames}`,
|
||||
`actions = create_action_presets(num_frames, keyboard_dim=${keyboardDim})`,
|
||||
`grid_sizes = torch.tensor([${Math.floor((config.frames - 1) / 4) + 1}, ${Math.floor(config.h / 8)}, ${Math.floor(config.w / 8)}])`,
|
||||
`num_frames = ${config.numFrames}`,
|
||||
`actions = create_action_presets(num_frames, keyboard_dim=${keyboardDim}, seed=1024)`,
|
||||
`grid_sizes = torch.tensor([${Math.floor((config.numFrames - 1) / 4) + 1}, ${Math.floor(config.height / 8)}, ${Math.floor(config.width / 8)}])`,
|
||||
"",
|
||||
"generator.generate_video(",
|
||||
' prompt="",',
|
||||
' image_path="./input.png",',
|
||||
' mouse_cond=actions["mouse"].unsqueeze(0),',
|
||||
' keyboard_cond=actions["keyboard"].unsqueeze(0),',
|
||||
" grid_sizes=grid_sizes,",
|
||||
` height=${config.h},`,
|
||||
` width=${config.w},`,
|
||||
` fps=${fps},`,
|
||||
" seed=42,",
|
||||
` num_frames=${config.frames},`,
|
||||
` num_inference_steps=${config.steps},`,
|
||||
` guidance_scale=${config.cfg.toFixed(1)},`,
|
||||
' output_path="outputs/",',
|
||||
" save_video=True,",
|
||||
")",
|
||||
"generator.generate({",
|
||||
' "prompt": "",',
|
||||
" \"inputs\": {",
|
||||
...inputLines,
|
||||
" },",
|
||||
" \"sampling\": {",
|
||||
` "height": ${config.height},`,
|
||||
` "width": ${config.width},`,
|
||||
` "fps": ${config.fps},`,
|
||||
" \"seed\": 1024,",
|
||||
` "num_frames": ${config.numFrames},`,
|
||||
` "num_inference_steps": ${config.numInferenceSteps},`,
|
||||
...(config.dmdDenoisingSteps === null ? [` "guidance_scale": ${config.guidanceScale},`] : []),
|
||||
...(config.boundaryRatio === null ? [] : [` "boundary_ratio": ${config.boundaryRatio},`]),
|
||||
" },",
|
||||
' "output": {"output_path": "outputs/", "save_video": True},',
|
||||
"})",
|
||||
].join("\n")
|
||||
}
|
||||
|
||||
const offloadYaml = [
|
||||
` dit: ${Boolean(config.ditCpuOffload)}`,
|
||||
` dit_layerwise: ${Boolean(config.ditLayerwiseOffload)}`,
|
||||
` text_encoder: ${Boolean(config.textEncoderCpuOffload)}`,
|
||||
" image_encoder: false",
|
||||
` vae: ${Boolean(config.vaeCpuOffload)}`,
|
||||
` pin_cpu_memory: ${Boolean(config.pinCpuMemory)}`,
|
||||
` dit: ${config.ditCpuOffload}`,
|
||||
` dit_layerwise: ${config.ditLayerwiseOffload}`,
|
||||
` text_encoder: ${config.textEncoderCpuOffload}`,
|
||||
` image_encoder: ${config.imageEncoderCpuOffload}`,
|
||||
` vae: ${config.vaeCpuOffload}`,
|
||||
` pin_cpu_memory: ${config.pinCpuMemory}`,
|
||||
]
|
||||
const inputsYaml = task === "i2v" || task === "ti2v"
|
||||
? [
|
||||
@@ -278,45 +218,56 @@ export default function FastVideoConfigSelector() {
|
||||
" image_path: ./input.png",
|
||||
]
|
||||
: []
|
||||
const fsdpYaml = config.useFsdpInference ? [" use_fsdp_inference: true"] : []
|
||||
const presetOverridesYaml = [
|
||||
" preset_overrides:",
|
||||
` embedded_cfg_scale: ${config.embeddedCfgScale}`,
|
||||
...(config.dmdDenoisingSteps === null
|
||||
? []
|
||||
: [` dmd_denoising_steps: [${config.dmdDenoisingSteps.join(", ")}]`]),
|
||||
]
|
||||
const experimentalYaml = config.defaultAttentionBackend === "VIDEO_SPARSE_ATTN"
|
||||
? [" experimental:", ` VSA_sparsity: ${config.vsaSparsity}`]
|
||||
: []
|
||||
|
||||
return [
|
||||
"# Install once:",
|
||||
"# pip install fastvideo",
|
||||
"",
|
||||
`# ${hardware.label} benchmark: ${formatTime(config.timeSec)} generation time${config.firstRunSec ? `, ${formatTime(config.firstRunSec)} first run including model load` : ""}.`,
|
||||
"",
|
||||
"cat > fastvideo-generate.yaml <<'YAML'",
|
||||
"generator:",
|
||||
` model_path: ${config.model}`,
|
||||
" engine:",
|
||||
` num_gpus: ${ngpu}`,
|
||||
` use_fsdp_inference: ${config.useFsdpInference}`,
|
||||
" offload:",
|
||||
...offloadYaml,
|
||||
...fsdpYaml,
|
||||
" pipeline:",
|
||||
` workload_type: ${workloadType}`,
|
||||
...presetOverridesYaml,
|
||||
...experimentalYaml,
|
||||
"",
|
||||
"request:",
|
||||
' prompt: "your prompt here"',
|
||||
...inputsYaml,
|
||||
" sampling:",
|
||||
` height: ${config.h}`,
|
||||
` width: ${config.w}`,
|
||||
` fps: ${fps}`,
|
||||
" seed: 42",
|
||||
` num_frames: ${config.frames}`,
|
||||
` num_inference_steps: ${config.steps}`,
|
||||
` guidance_scale: ${config.cfg.toFixed(1)}`,
|
||||
` height: ${config.height}`,
|
||||
` width: ${config.width}`,
|
||||
` fps: ${config.fps}`,
|
||||
" seed: 1024",
|
||||
` num_frames: ${config.numFrames}`,
|
||||
` num_inference_steps: ${config.numInferenceSteps}`,
|
||||
...(config.dmdDenoisingSteps === null ? [` guidance_scale: ${config.guidanceScale}`] : []),
|
||||
...(config.guidanceScale2 === null ? [] : [` guidance_scale_2: ${config.guidanceScale2}`]),
|
||||
...(config.boundaryRatio === null ? [] : [` boundary_ratio: ${config.boundaryRatio}`]),
|
||||
" output:",
|
||||
" output_path: outputs/",
|
||||
" save_video: true",
|
||||
"YAML",
|
||||
"",
|
||||
`FASTVIDEO_ATTENTION_BACKEND=${config.attn} \\`,
|
||||
`FASTVIDEO_ATTENTION_BACKEND=${config.defaultAttentionBackend} \\`,
|
||||
" fastvideo generate --config fastvideo-generate.yaml",
|
||||
].join("\n")
|
||||
}, [config, hardware.label, ngpu, task])
|
||||
}, [config, ngpu, task])
|
||||
|
||||
const copyCommand = async () => {
|
||||
if (!command) return
|
||||
@@ -326,7 +277,7 @@ export default function FastVideoConfigSelector() {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-white text-foreground">
|
||||
<div id="config-generator-root" className="bg-white text-foreground">
|
||||
<div className="max-w-4xl px-6 py-8">
|
||||
{/* Step 1: Task Selection */}
|
||||
<section className="mb-8">
|
||||
@@ -339,8 +290,10 @@ export default function FastVideoConfigSelector() {
|
||||
const Icon = ICONS[icon as IconName] ?? Film
|
||||
return (
|
||||
<button
|
||||
type="button"
|
||||
key={id}
|
||||
onClick={() => setTask(id)}
|
||||
aria-pressed={task === id}
|
||||
className={`group relative rounded-xl border p-4 text-left transition-all duration-200 hover:border-primary/50 ${
|
||||
task === id
|
||||
? "border-primary bg-primary/10 shadow-lg shadow-primary/10"
|
||||
@@ -362,68 +315,19 @@ export default function FastVideoConfigSelector() {
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Step 2: Machine Specs */}
|
||||
{/* Step 2: Parallelism */}
|
||||
<section className="mb-8">
|
||||
<div className="mb-4 flex items-center gap-2">
|
||||
<span className="flex h-6 w-6 items-center justify-center rounded-full bg-primary text-xs font-medium text-primary-foreground">2</span>
|
||||
<h2 className="text-sm font-semibold uppercase tracking-wider text-primary">Your machine specs</h2>
|
||||
<h2 className="text-sm font-semibold uppercase tracking-wider text-primary">Parallelism</h2>
|
||||
</div>
|
||||
<div className="grid grid-cols-2 gap-3 sm:grid-cols-4">
|
||||
<div className="rounded-xl border border-border bg-card p-4">
|
||||
<div className="mb-2 flex items-center gap-2 text-primary">
|
||||
<Monitor className="h-4 w-4" />
|
||||
<span className="text-xs font-semibold uppercase tracking-wide">GPU Model</span>
|
||||
</div>
|
||||
<select
|
||||
value={gpu}
|
||||
onChange={(e) => {
|
||||
const nextGpu = e.target.value
|
||||
setGpu(nextGpu)
|
||||
setVram(HARDWARE_BY_ID[nextGpu].defaultVramGb)
|
||||
}}
|
||||
className="w-full rounded-lg border border-border bg-card px-3 py-2 text-sm text-card-foreground outline-none transition-colors focus:border-primary/50"
|
||||
>
|
||||
{HARDWARE.map((option) => (
|
||||
<option key={option.id} value={option.id}>{option.label}</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
<div className="rounded-xl border border-border bg-card p-4">
|
||||
<div className="mb-2 flex items-center gap-2 text-primary">
|
||||
<Cpu className="h-4 w-4" />
|
||||
<span className="text-xs font-semibold uppercase tracking-wide">VRAM (GB)</span>
|
||||
</div>
|
||||
<select
|
||||
value={vram}
|
||||
onChange={(e) => setVram(Number(e.target.value))}
|
||||
className="w-full rounded-lg border border-border bg-card px-3 py-2 text-sm text-card-foreground outline-none transition-colors focus:border-primary/50"
|
||||
>
|
||||
{hardware.vramOptionsGb.map((option) => (
|
||||
<option key={option} value={option}>{option} GB</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
<div className="rounded-xl border border-border bg-card p-4">
|
||||
<div className="mb-2 flex items-center gap-2 text-primary">
|
||||
<HardDrive className="h-4 w-4" />
|
||||
<span className="text-xs font-semibold uppercase tracking-wide">RAM (GB)</span>
|
||||
</div>
|
||||
<select
|
||||
value={ram}
|
||||
onChange={(e) => setRam(Number(e.target.value))}
|
||||
className="w-full rounded-lg border border-border bg-card px-3 py-2 text-sm text-card-foreground outline-none transition-colors focus:border-primary/50"
|
||||
>
|
||||
{RAM_OPTIONS.map((option) => (
|
||||
<option key={option} value={option}>{option} GB</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
<div className="rounded-xl border border-border bg-card p-4">
|
||||
<div className="mb-2 flex items-center gap-2 text-primary">
|
||||
<div className="max-w-xs rounded-xl border border-border bg-card p-4">
|
||||
<label htmlFor="quick-gpu-count" className="mb-2 flex items-center gap-2 text-primary">
|
||||
<Layers className="h-4 w-4" />
|
||||
<span className="text-xs font-semibold uppercase tracking-wide">Number of GPUs</span>
|
||||
</div>
|
||||
</label>
|
||||
<select
|
||||
id="quick-gpu-count"
|
||||
value={ngpu}
|
||||
onChange={(e) => setNgpu(Number(e.target.value))}
|
||||
className="w-full rounded-lg border border-border bg-card px-3 py-2 text-sm text-card-foreground outline-none transition-colors focus:border-primary/50"
|
||||
@@ -432,23 +336,25 @@ export default function FastVideoConfigSelector() {
|
||||
<option key={option} value={option}>{option} GPU{option === 1 ? "" : "s"}</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Step 3: Output Mode */}
|
||||
{/* Step 3: Model profile */}
|
||||
<section className="mb-8">
|
||||
<div className="mb-4 flex items-center gap-2">
|
||||
<span className="flex h-6 w-6 items-center justify-center rounded-full bg-primary text-xs font-medium text-primary-foreground">3</span>
|
||||
<h2 className="text-sm font-semibold uppercase tracking-wider text-primary">Output mode</h2>
|
||||
<h2 className="text-sm font-semibold uppercase tracking-wider text-primary">Model profile</h2>
|
||||
</div>
|
||||
<div className="grid gap-3 sm:grid-cols-4">
|
||||
{TIERS.map(({ id, name, desc, badge }) => {
|
||||
const tierConfig = getProfile(task, id, gpu, vram)
|
||||
const tierConfig = getProfile(task, id)
|
||||
const tierModel = tierConfig ? MODEL_BY_ID[tierConfig.model] : undefined
|
||||
return (
|
||||
<button
|
||||
type="button"
|
||||
key={id}
|
||||
onClick={() => setTier(id)}
|
||||
aria-pressed={tier === id}
|
||||
className={`group relative rounded-xl border p-4 text-left transition-all duration-200 sm:col-span-2 ${
|
||||
tier === id
|
||||
? "border-primary bg-primary/10 shadow-lg shadow-primary/10"
|
||||
@@ -465,18 +371,11 @@ export default function FastVideoConfigSelector() {
|
||||
</div>
|
||||
<p className="mt-1 text-xs leading-relaxed text-muted-foreground">{desc}</p>
|
||||
<div className="mt-3 space-y-1 border-t border-border pt-3">
|
||||
{tierConfig ? (
|
||||
<>
|
||||
<div className="flex items-center gap-1.5 text-xs text-muted-foreground">
|
||||
<span className="font-semibold">INF</span>
|
||||
<InfoTip content="Inference time only — the compute to generate the video once the model is loaded. The first run takes longer because it also loads the model." />
|
||||
<span>{formatTime(tierConfig.timeSec)}</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-1.5 text-xs text-muted-foreground">
|
||||
<span className="font-semibold">VRAM</span>
|
||||
<span>{tierConfig.vram}</span>
|
||||
</div>
|
||||
</>
|
||||
{tierModel ? (
|
||||
<div className="text-xs text-muted-foreground">
|
||||
<span className="font-semibold">{tierModel.name}</span>
|
||||
{` · ${tierModel.recipe.width}×${tierModel.recipe.height} · ${tierModel.recipe.numInferenceSteps} steps`}
|
||||
</div>
|
||||
) : (
|
||||
<div className="text-xs font-medium text-muted-foreground">
|
||||
Not suitable
|
||||
@@ -487,11 +386,6 @@ export default function FastVideoConfigSelector() {
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
{warning && (
|
||||
<div className="mt-3 rounded-lg border border-destructive/20 bg-destructive/10 px-4 py-3 text-sm text-destructive">
|
||||
{warning}
|
||||
</div>
|
||||
)}
|
||||
</section>
|
||||
|
||||
{/* Output Configuration */}
|
||||
@@ -504,24 +398,25 @@ export default function FastVideoConfigSelector() {
|
||||
</div>
|
||||
<div className="overflow-hidden rounded-2xl border border-border bg-card">
|
||||
{/* Meta Cards */}
|
||||
<div className="grid grid-cols-3 divide-x divide-border border-b border-border">
|
||||
<div className="grid grid-cols-1 divide-y divide-border border-b border-border sm:grid-cols-3 sm:divide-x sm:divide-y-0">
|
||||
<div className="p-4">
|
||||
<div className="text-xs font-semibold uppercase tracking-wide text-muted-foreground">Model</div>
|
||||
<div className="mt-1 font-mono text-sm text-card-foreground">{config?.modelShort ?? "Unavailable"}</div>
|
||||
<div className="mt-1 font-mono text-sm text-card-foreground">{config?.name ?? "Unavailable"}</div>
|
||||
</div>
|
||||
<div className="p-4">
|
||||
<div className="text-xs font-semibold uppercase tracking-wide text-muted-foreground">Est. Generation Time</div>
|
||||
<div className="mt-1 font-mono text-sm text-card-foreground">{config ? formatTime(config.timeSec) : "Unavailable"}</div>
|
||||
<div className="text-xs font-semibold uppercase tracking-wide text-muted-foreground">Resolution</div>
|
||||
<div className="mt-1 font-mono text-sm text-card-foreground">{config ? `${config.width}×${config.height}` : "Unavailable"}</div>
|
||||
</div>
|
||||
<div className="p-4">
|
||||
<div className="text-xs font-semibold uppercase tracking-wide text-muted-foreground">Peak VRAM</div>
|
||||
<div className="mt-1 font-mono text-sm text-card-foreground">{config?.vram ?? "Unavailable"}</div>
|
||||
<div className="text-xs font-semibold uppercase tracking-wide text-muted-foreground">Denoising</div>
|
||||
<div className="mt-1 font-mono text-sm text-card-foreground">{config ? `${config.numInferenceSteps} steps` : "Unavailable"}</div>
|
||||
</div>
|
||||
</div>
|
||||
{/* Command Block */}
|
||||
<div className="relative p-4">
|
||||
{command && (
|
||||
<button
|
||||
type="button"
|
||||
onClick={copyCommand}
|
||||
className="absolute right-4 top-4 flex items-center gap-2 rounded-lg border border-border bg-card px-4 py-2 text-sm font-medium text-muted-foreground transition-all hover:border-primary/50 hover:bg-primary/10 hover:text-primary"
|
||||
>
|
||||
@@ -535,7 +430,7 @@ export default function FastVideoConfigSelector() {
|
||||
</pre>
|
||||
) : (
|
||||
<div className="rounded-lg border border-dashed border-border px-4 py-6 text-sm text-muted-foreground">
|
||||
{`${hardware.label} (${vram} GB) is not suitable for ${tier === "quick" ? "Quick Generate" : "High Quality"} on this task.`}
|
||||
No maintained profile is available for this task and model choice.
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -75,8 +75,8 @@
|
||||
}
|
||||
|
||||
@theme inline {
|
||||
--font-sans: 'Geist', 'Geist Fallback';
|
||||
--font-mono: 'Geist Mono', 'Geist Mono Fallback';
|
||||
--font-sans: ui-sans-serif, system-ui, sans-serif;
|
||||
--font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
|
||||
--color-background: var(--background);
|
||||
--color-foreground: var(--foreground);
|
||||
--color-card: var(--card);
|
||||
|
||||
@@ -1,13 +1,9 @@
|
||||
import type { Metadata } from 'next'
|
||||
import { Geist, Geist_Mono } from 'next/font/google'
|
||||
import './globals.css'
|
||||
|
||||
const _geist = Geist({ subsets: ["latin"] });
|
||||
const _geistMono = Geist_Mono({ subsets: ["latin"] });
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: 'FastVideo Config Generator',
|
||||
description: 'Choose your hardware and task to generate a FastVideo configuration command',
|
||||
description: 'Choose a maintained FastVideo recipe and generate an executable configuration',
|
||||
}
|
||||
|
||||
export default function RootLayout({
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2,380 +2,124 @@
|
||||
"defaults": {
|
||||
"task": "t2v",
|
||||
"tier": "quick",
|
||||
"gpu": "5090",
|
||||
"ramGb": 64,
|
||||
"numGpus": 1
|
||||
},
|
||||
"ramOptionsGb": [128, 64, 32],
|
||||
"gpuCountOptions": [1, 2, 4],
|
||||
"hardware": [
|
||||
{
|
||||
"id": "4090",
|
||||
"label": "RTX 4090",
|
||||
"defaultVramGb": 24,
|
||||
"vramOptionsGb": [24]
|
||||
},
|
||||
{
|
||||
"id": "5090",
|
||||
"label": "RTX 5090",
|
||||
"defaultVramGb": 32,
|
||||
"vramOptionsGb": [32]
|
||||
}
|
||||
],
|
||||
"tasks": [
|
||||
{
|
||||
"id": "t2v",
|
||||
"label": "Text to Video",
|
||||
"sub": "T2V",
|
||||
"icon": "Film"
|
||||
},
|
||||
{
|
||||
"id": "i2v",
|
||||
"label": "Image to Video",
|
||||
"sub": "I2V",
|
||||
"icon": "Image"
|
||||
},
|
||||
{
|
||||
"id": "ti2v",
|
||||
"label": "Text + Image",
|
||||
"sub": "TI2V",
|
||||
"icon": "Sparkles"
|
||||
},
|
||||
{
|
||||
"id": "game",
|
||||
"label": "Game",
|
||||
"sub": "Matrix Game",
|
||||
"icon": "Gamepad2"
|
||||
}
|
||||
{ "id": "t2v", "label": "Text to Video", "sub": "T2V", "icon": "Film" },
|
||||
{ "id": "i2v", "label": "Image to Video", "sub": "I2V", "icon": "Image" },
|
||||
{ "id": "ti2v", "label": "Text + Image", "sub": "TI2V", "icon": "Sparkles" },
|
||||
{ "id": "game", "label": "Game", "sub": "Matrix Game", "icon": "Gamepad2" }
|
||||
],
|
||||
"tiers": [
|
||||
{
|
||||
"id": "quick",
|
||||
"name": "Quick Generate",
|
||||
"desc": "FastVideo model with a benchmarked fast profile.",
|
||||
"badge": "Recommended"
|
||||
"name": "Recommended",
|
||||
"desc": "The maintained FastVideo example for this task.",
|
||||
"badge": "Start here"
|
||||
},
|
||||
{
|
||||
"id": "best",
|
||||
"name": "High Quality",
|
||||
"desc": "FastVideo model with a benchmarked quality-oriented profile."
|
||||
"name": "Alternative",
|
||||
"desc": "Another maintained model or task variant."
|
||||
}
|
||||
],
|
||||
"profiles": [
|
||||
{
|
||||
"status": "available",
|
||||
"gpu": "5090",
|
||||
"vramGb": 32,
|
||||
"task": "t2v",
|
||||
"tier": "quick",
|
||||
"model": "FastVideo/FastWan2.1-T2V-1.3B-Diffusers",
|
||||
"modelShort": "FastWan2.1-T2V-1.3B",
|
||||
"attn": "VIDEO_SPARSE_ATTN",
|
||||
"h": 480,
|
||||
"w": 832,
|
||||
"frames": 81,
|
||||
"steps": 40,
|
||||
"cfg": 5,
|
||||
"fps": 16,
|
||||
"vramMin": 18,
|
||||
"ramMin": 64,
|
||||
"timeSec": 22.91,
|
||||
"firstRunSec": 139.44,
|
||||
"vram": "~16.0 GB",
|
||||
"offload": true,
|
||||
"ditCpuOffload": true,
|
||||
"ditLayerwiseOffload": true,
|
||||
"vaeCpuOffload": true,
|
||||
"ditCpuOffload": false,
|
||||
"ditLayerwiseOffload": false,
|
||||
"vaeCpuOffload": false,
|
||||
"textEncoderCpuOffload": true,
|
||||
"pinCpuMemory": true
|
||||
"imageEncoderCpuOffload": false,
|
||||
"pinCpuMemory": true,
|
||||
"useFsdpInference": false
|
||||
},
|
||||
{
|
||||
"status": "available",
|
||||
"gpu": "5090",
|
||||
"vramGb": 32,
|
||||
"task": "t2v",
|
||||
"tier": "best",
|
||||
"model": "FastVideo/FastHunyuan-diffusers",
|
||||
"modelShort": "FastHunyuan",
|
||||
"attn": "FLASH_ATTN",
|
||||
"h": 720,
|
||||
"w": 1280,
|
||||
"frames": 81,
|
||||
"steps": 50,
|
||||
"cfg": 1,
|
||||
"fps": 24,
|
||||
"vramMin": 32,
|
||||
"ramMin": 64,
|
||||
"timeSec": 1389.71,
|
||||
"firstRunSec": 1492.36,
|
||||
"vram": "~27.1 GB",
|
||||
"offload": true,
|
||||
"model": "Wan-AI/Wan2.1-T2V-14B-Diffusers",
|
||||
"ditCpuOffload": true,
|
||||
"ditLayerwiseOffload": true,
|
||||
"vaeCpuOffload": true,
|
||||
"textEncoderCpuOffload": true,
|
||||
"pinCpuMemory": true
|
||||
},
|
||||
{
|
||||
"status": "available",
|
||||
"gpu": "5090",
|
||||
"vramGb": 32,
|
||||
"task": "ti2v",
|
||||
"tier": "quick",
|
||||
"model": "FastVideo/FastWan2.2-TI2V-5B-FullAttn-Diffusers",
|
||||
"modelShort": "FastWan2.2-TI2V-5B",
|
||||
"attn": "VIDEO_SPARSE_ATTN",
|
||||
"h": 480,
|
||||
"w": 832,
|
||||
"frames": 81,
|
||||
"steps": 40,
|
||||
"cfg": 5,
|
||||
"fps": 16,
|
||||
"vramMin": 18,
|
||||
"ramMin": 64,
|
||||
"timeSec": 17.39,
|
||||
"firstRunSec": 116.57,
|
||||
"vram": "~17.2 GB",
|
||||
"offload": true,
|
||||
"ditCpuOffload": true,
|
||||
"ditLayerwiseOffload": true,
|
||||
"ditLayerwiseOffload": false,
|
||||
"vaeCpuOffload": false,
|
||||
"textEncoderCpuOffload": true,
|
||||
"imageEncoderCpuOffload": false,
|
||||
"pinCpuMemory": true,
|
||||
"extra": "--image ./input.png"
|
||||
"useFsdpInference": false
|
||||
},
|
||||
{
|
||||
"status": "available",
|
||||
"gpu": "5090",
|
||||
"vramGb": 32,
|
||||
"task": "game",
|
||||
"tier": "quick",
|
||||
"model": "FastVideo/Matrix-Game-2.0-Base-Diffusers",
|
||||
"modelShort": "Matrix-Game-2.0-Base",
|
||||
"attn": "FLASH_ATTN",
|
||||
"h": 352,
|
||||
"w": 640,
|
||||
"frames": 81,
|
||||
"steps": 3,
|
||||
"cfg": 5,
|
||||
"fps": 16,
|
||||
"vramMin": 12,
|
||||
"ramMin": 32,
|
||||
"timeSec": 12.29,
|
||||
"firstRunSec": 247.2,
|
||||
"vram": "~10.4 GB",
|
||||
"offload": true,
|
||||
"ditCpuOffload": true,
|
||||
"ditLayerwiseOffload": true,
|
||||
"textEncoderCpuOffload": true,
|
||||
"pinCpuMemory": true,
|
||||
"keyboardDim": 4,
|
||||
"extra": "--image ./input.png --action forward"
|
||||
},
|
||||
{
|
||||
"status": "available",
|
||||
"gpu": "5090",
|
||||
"vramGb": 32,
|
||||
"task": "game",
|
||||
"tier": "best",
|
||||
"model": "FastVideo/Matrix-Game-2.0-GTA-Diffusers",
|
||||
"modelShort": "Matrix-Game-2.0-GTA",
|
||||
"attn": "FLASH_ATTN",
|
||||
"h": 352,
|
||||
"w": 640,
|
||||
"frames": 81,
|
||||
"steps": 3,
|
||||
"cfg": 5,
|
||||
"fps": 16,
|
||||
"vramMin": 12,
|
||||
"ramMin": 32,
|
||||
"timeSec": 13.03,
|
||||
"firstRunSec": 212.37,
|
||||
"vram": "~10.4 GB",
|
||||
"offload": true,
|
||||
"ditCpuOffload": true,
|
||||
"ditLayerwiseOffload": true,
|
||||
"textEncoderCpuOffload": true,
|
||||
"pinCpuMemory": true,
|
||||
"keyboardDim": 2,
|
||||
"extra": "--image ./input.png --action forward"
|
||||
},
|
||||
{
|
||||
"status": "available",
|
||||
"gpu": "5090",
|
||||
"vramGb": 32,
|
||||
"task": "ti2v",
|
||||
"tier": "best",
|
||||
"model": "Wan-AI/Wan2.2-TI2V-5B-Diffusers",
|
||||
"modelShort": "Wan2.2-TI2V-5B",
|
||||
"attn": "FLASH_ATTN",
|
||||
"h": 480,
|
||||
"w": 832,
|
||||
"frames": 81,
|
||||
"steps": 40,
|
||||
"cfg": 5,
|
||||
"fps": 16,
|
||||
"vramMin": 18,
|
||||
"ramMin": 64,
|
||||
"timeSec": 71.01,
|
||||
"firstRunSec": 223.29,
|
||||
"vram": "~15.5 GB",
|
||||
"offload": true,
|
||||
"ditCpuOffload": true,
|
||||
"ditLayerwiseOffload": true,
|
||||
"textEncoderCpuOffload": true,
|
||||
"pinCpuMemory": true,
|
||||
"extra": "--image ./input.png"
|
||||
},
|
||||
{
|
||||
"status": "available",
|
||||
"gpu": "5090",
|
||||
"vramGb": 32,
|
||||
"task": "i2v",
|
||||
"tier": "best",
|
||||
"model": "Wan-AI/Wan2.1-I2V-14B-720P-Diffusers",
|
||||
"modelShort": "Wan2.1-I2V-720P",
|
||||
"attn": "FLASH_ATTN",
|
||||
"h": 720,
|
||||
"w": 1280,
|
||||
"frames": 81,
|
||||
"steps": 40,
|
||||
"cfg": 5,
|
||||
"fps": 16,
|
||||
"vramMin": 32,
|
||||
"ramMin": 64,
|
||||
"timeSec": 2832.76,
|
||||
"firstRunSec": 3026.41,
|
||||
"vram": "~28.9 GB",
|
||||
"offload": true,
|
||||
"ditCpuOffload": true,
|
||||
"vaeCpuOffload": true,
|
||||
"textEncoderCpuOffload": true,
|
||||
"pinCpuMemory": true,
|
||||
"useFsdpInference": true,
|
||||
"extra": "--image ./input.png"
|
||||
},
|
||||
{
|
||||
"status": "available",
|
||||
"gpu": "5090",
|
||||
"vramGb": 32,
|
||||
"task": "i2v",
|
||||
"tier": "quick",
|
||||
"model": "loayrashid/TurboWan2.2-I2V-A14B-Diffusers",
|
||||
"modelShort": "TurboWan2.2-I2V-A14B",
|
||||
"attn": "SLA_ATTN",
|
||||
"h": 480,
|
||||
"w": 832,
|
||||
"frames": 81,
|
||||
"steps": 4,
|
||||
"cfg": 1,
|
||||
"fps": 16,
|
||||
"vramMin": 32,
|
||||
"ramMin": 64,
|
||||
"timeSec": 364,
|
||||
"vram": "~10.6 GB",
|
||||
"offload": true,
|
||||
"ditCpuOffload": true,
|
||||
"ditLayerwiseOffload": false,
|
||||
"vaeCpuOffload": false,
|
||||
"textEncoderCpuOffload": true,
|
||||
"imageEncoderCpuOffload": true,
|
||||
"pinCpuMemory": true,
|
||||
"useFsdpInference": true,
|
||||
"extra": "--image ./input.png"
|
||||
"useFsdpInference": false
|
||||
},
|
||||
{
|
||||
"status": "available",
|
||||
"gpu": "4090",
|
||||
"vramGb": 24,
|
||||
"task": "t2v",
|
||||
"tier": "quick",
|
||||
"model": "FastVideo/FastWan2.1-T2V-1.3B-Diffusers",
|
||||
"modelShort": "FastWan2.1-T2V-1.3B",
|
||||
"attn": "VIDEO_SPARSE_ATTN",
|
||||
"h": 480,
|
||||
"w": 832,
|
||||
"frames": 81,
|
||||
"steps": 3,
|
||||
"cfg": 6,
|
||||
"fps": 16,
|
||||
"vramMin": 12,
|
||||
"ramMin": 32,
|
||||
"timeSec": 32.42,
|
||||
"vram": "~11.0 GB",
|
||||
"offload": true,
|
||||
"ditLayerwiseOffload": true,
|
||||
"textEncoderCpuOffload": true
|
||||
"task": "i2v",
|
||||
"tier": "best",
|
||||
"model": "Wan-AI/Wan2.1-I2V-14B-720P-Diffusers",
|
||||
"ditCpuOffload": true,
|
||||
"ditLayerwiseOffload": false,
|
||||
"vaeCpuOffload": false,
|
||||
"textEncoderCpuOffload": true,
|
||||
"imageEncoderCpuOffload": true,
|
||||
"pinCpuMemory": true,
|
||||
"useFsdpInference": false
|
||||
},
|
||||
{
|
||||
"status": "available",
|
||||
"gpu": "4090",
|
||||
"vramGb": 24,
|
||||
"task": "ti2v",
|
||||
"tier": "quick",
|
||||
"model": "FastVideo/FastWan2.2-TI2V-5B-FullAttn-Diffusers",
|
||||
"modelShort": "FastWan2.2-TI2V-5B",
|
||||
"attn": "FLASH_ATTN",
|
||||
"h": 480,
|
||||
"w": 832,
|
||||
"frames": 81,
|
||||
"steps": 3,
|
||||
"cfg": 6,
|
||||
"fps": 16,
|
||||
"vramMin": 12,
|
||||
"ramMin": 64,
|
||||
"timeSec": 17.81,
|
||||
"vram": "~10.8 GB",
|
||||
"offload": true,
|
||||
"ditLayerwiseOffload": true,
|
||||
"ditCpuOffload": true,
|
||||
"ditLayerwiseOffload": false,
|
||||
"vaeCpuOffload": false,
|
||||
"textEncoderCpuOffload": true,
|
||||
"extra": "--image ./input.png"
|
||||
"imageEncoderCpuOffload": true,
|
||||
"pinCpuMemory": true,
|
||||
"useFsdpInference": false
|
||||
},
|
||||
{
|
||||
"task": "ti2v",
|
||||
"tier": "best",
|
||||
"model": "Wan-AI/Wan2.2-TI2V-5B-Diffusers",
|
||||
"ditCpuOffload": true,
|
||||
"ditLayerwiseOffload": false,
|
||||
"vaeCpuOffload": false,
|
||||
"textEncoderCpuOffload": true,
|
||||
"imageEncoderCpuOffload": true,
|
||||
"pinCpuMemory": true,
|
||||
"useFsdpInference": false
|
||||
},
|
||||
{
|
||||
"status": "available",
|
||||
"gpu": "4090",
|
||||
"vramGb": 24,
|
||||
"task": "game",
|
||||
"tier": "quick",
|
||||
"model": "FastVideo/Matrix-Game-2.0-Base-Diffusers",
|
||||
"modelShort": "Matrix-Game-2.0-Base",
|
||||
"attn": "FLASH_ATTN",
|
||||
"h": 480,
|
||||
"w": 832,
|
||||
"frames": 81,
|
||||
"steps": 3,
|
||||
"cfg": 6,
|
||||
"fps": 16,
|
||||
"vramMin": 12,
|
||||
"ramMin": 32,
|
||||
"timeSec": 23.81,
|
||||
"vram": "~11.2 GB",
|
||||
"offload": true,
|
||||
"ditLayerwiseOffload": true,
|
||||
"model": "FastVideo/Matrix-Game-2.0-Base-Distilled-Diffusers",
|
||||
"ditCpuOffload": true,
|
||||
"ditLayerwiseOffload": false,
|
||||
"vaeCpuOffload": false,
|
||||
"textEncoderCpuOffload": true,
|
||||
"keyboardDim": 4,
|
||||
"extra": "--image ./input.png --action forward"
|
||||
"imageEncoderCpuOffload": true,
|
||||
"pinCpuMemory": true,
|
||||
"useFsdpInference": false
|
||||
},
|
||||
{
|
||||
"status": "available",
|
||||
"gpu": "4090",
|
||||
"vramGb": 24,
|
||||
"task": "game",
|
||||
"tier": "best",
|
||||
"model": "FastVideo/Matrix-Game-2.0-GTA-Diffusers",
|
||||
"modelShort": "Matrix-Game-2.0-GTA",
|
||||
"attn": "FLASH_ATTN",
|
||||
"h": 480,
|
||||
"w": 832,
|
||||
"frames": 81,
|
||||
"steps": 3,
|
||||
"cfg": 6,
|
||||
"fps": 16,
|
||||
"vramMin": 12,
|
||||
"ramMin": 32,
|
||||
"timeSec": 24.24,
|
||||
"vram": "~11.2 GB",
|
||||
"offload": true,
|
||||
"ditLayerwiseOffload": true,
|
||||
"model": "FastVideo/Matrix-Game-2.0-GTA-Distilled-Diffusers",
|
||||
"ditCpuOffload": true,
|
||||
"ditLayerwiseOffload": false,
|
||||
"vaeCpuOffload": false,
|
||||
"textEncoderCpuOffload": true,
|
||||
"keyboardDim": 2,
|
||||
"extra": "--image ./input.png --action forward"
|
||||
"imageEncoderCpuOffload": true,
|
||||
"pinCpuMemory": true,
|
||||
"useFsdpInference": false
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
+149
-82
@@ -1,103 +1,170 @@
|
||||
{
|
||||
"_comment": "Single data source for the Advanced Tuning page (app/tuning/adv_page.tsx). Each benchmark run is one real measured configuration. The page filters by workload + GPU and never estimates benchmark values.",
|
||||
"source": {
|
||||
"fastvideoCommit": "a2bfc7cdb2a1de2b138258412e42d183444ffe09",
|
||||
"description": "Defaults transcribed from FastVideo's registered inference presets, pipeline configs, maintained examples, and support matrix at this commit.",
|
||||
"paths": [
|
||||
"fastvideo/registry.py",
|
||||
"fastvideo/pipelines/basic/*/presets.py",
|
||||
"fastvideo/configs/pipelines/*.py",
|
||||
"examples/inference/basic/*.py",
|
||||
"docs/inference/support_matrix.md"
|
||||
]
|
||||
},
|
||||
"defaults": {
|
||||
"model_id": "FastVideo/FastWan2.1-T2V-1.3B-Diffusers",
|
||||
"workload_type": "t2v",
|
||||
"gpu": "rtx5090",
|
||||
"num_gpus": 1,
|
||||
"height": 480,
|
||||
"width": 832,
|
||||
"num_frames": 81,
|
||||
"fps": 24,
|
||||
"num_inference_steps": 40,
|
||||
"guidance_scale": 5,
|
||||
"embedded_cfg_scale": 6,
|
||||
"flow_shift": null,
|
||||
"seed": -1,
|
||||
"attention_backend": "VIDEO_SPARSE_ATTN",
|
||||
"VSA_sparsity": 0,
|
||||
"dmd_denoising_steps": "1000,757,522",
|
||||
"seed": 1024,
|
||||
"dit_cpu_offload": false,
|
||||
"dit_layerwise_offload": false,
|
||||
"vae_cpu_offload": false,
|
||||
"text_encoder_cpu_offload": false,
|
||||
"text_encoder_cpu_offload": true,
|
||||
"image_encoder_cpu_offload": false,
|
||||
"pin_cpu_memory": false,
|
||||
"pin_cpu_memory": true,
|
||||
"use_fsdp_inference": false
|
||||
},
|
||||
"workloads": [
|
||||
{ "id": "t2v", "name": "Text to Video", "icon": "Film" },
|
||||
{ "id": "i2v", "name": "Image to Video", "icon": "Sparkles" },
|
||||
{ "id": "ti2v", "name": "Text+Image to Video", "icon": "Layers" },
|
||||
{ "id": "ti2v", "name": "Text + Image to Video", "icon": "Layers" },
|
||||
{ "id": "game", "name": "Game", "icon": "Zap" }
|
||||
],
|
||||
"gpus": [
|
||||
{ "id": "rtx4090", "name": "RTX 4090", "vram": "24GB" },
|
||||
{ "id": "rtx5090", "name": "RTX 5090", "vram": "32GB" }
|
||||
],
|
||||
"resolutionPresets": [
|
||||
{ "height": 480, "width": 832, "label": "480p (832x480)" },
|
||||
{ "height": 720, "width": 1280, "label": "720p (1280x720)" },
|
||||
{ "height": 1080, "width": 1920, "label": "1080p (1920x1080)" }
|
||||
],
|
||||
"framePresets": [
|
||||
{ "frames": 49, "label": "49 frames (~2s @24fps)" },
|
||||
{ "frames": 81, "label": "81 frames (~3.4s @24fps)" },
|
||||
{ "frames": 121, "label": "121 frames (~5s @24fps)" }
|
||||
],
|
||||
"attentionBackends": [
|
||||
{ "id": "FLASH_ATTN", "name": "Flash Attention", "shortName": "Flash", "desc": "Best quality-speed trade-off", "speed": "Baseline" },
|
||||
{ "id": "VIDEO_SPARSE_ATTN", "name": "Video Sparse Attention", "shortName": "VSA", "desc": "~30% faster, minimal quality loss", "speed": "Fast" },
|
||||
{ "id": "SAGE_ATTN", "name": "Sage Attention", "shortName": "SAGE", "desc": "~40% faster, visible at high motion", "speed": "Faster" },
|
||||
{ "id": "SLA_ATTN", "name": "Sparse-Linear Attention", "shortName": "SLA", "desc": "Requires SLA-tuned model checkpoint", "speed": "Fast" }
|
||||
{ "id": "FLASH_ATTN", "name": "Flash Attention", "shortName": "Flash", "desc": "Default dense attention backend." },
|
||||
{ "id": "VIDEO_SPARSE_ATTN", "name": "Video Sparse Attention", "shortName": "VSA", "desc": "Use only with models marked VSA-compatible." },
|
||||
{ "id": "SAGE_ATTN", "name": "Sage Attention", "shortName": "SAGE", "desc": "Quantized attention for models marked Sage-compatible." },
|
||||
{ "id": "SLA_ATTN", "name": "Sparse-Linear Attention", "shortName": "SLA", "desc": "Required by TurboDiffusion checkpoints." }
|
||||
],
|
||||
"models": [
|
||||
{ "id": "FastVideo/FastWan2.1-T2V-1.3B-Diffusers", "name": "FastWan2.1 T2V", "size": "1.3B", "workload": "t2v", "dmdMode": true, "dmdNote": "FastWan DMD uses 3-step distillation for faster generation." },
|
||||
{ "id": "FastVideo/FastWan2.2-TI2V-5B-FullAttn-Diffusers", "name": "FastWan2.2 TI2V FullAttn", "size": "5B", "workload": "ti2v", "dmdMode": true, "dmdNote": "FastWan DMD uses 3-step distillation for faster generation." },
|
||||
{ "id": "Wan-AI/Wan2.2-TI2V-5B-Diffusers", "name": "Wan2.2 TI2V", "size": "5B", "workload": "ti2v" },
|
||||
{ "id": "Wan-AI/Wan2.2-T2V-A14B-Diffusers", "name": "Wan2.2 T2V", "size": "A14B", "workload": "t2v" },
|
||||
{ "id": "Wan-AI/Wan2.2-I2V-A14B-Diffusers", "name": "Wan2.2 I2V", "size": "A14B", "workload": "i2v" },
|
||||
{ "id": "hunyuanvideo-community/HunyuanVideo", "name": "HunyuanVideo", "size": "13B", "workload": "t2v" },
|
||||
{ "id": "FastVideo/FastHunyuan-diffusers", "name": "FastHunyuan", "size": "13B", "workload": "t2v" },
|
||||
{ "id": "Wan-AI/Wan2.1-T2V-1.3B-Diffusers", "name": "Wan2.1 T2V", "size": "1.3B", "workload": "t2v" },
|
||||
{ "id": "Wan-AI/Wan2.1-T2V-14B-Diffusers", "name": "Wan2.1 T2V", "size": "14B", "workload": "t2v" },
|
||||
{ "id": "Wan-AI/Wan2.1-I2V-14B-480P-Diffusers", "name": "Wan2.1 I2V 480P", "size": "14B", "workload": "i2v" },
|
||||
{ "id": "Wan-AI/Wan2.1-I2V-14B-720P-Diffusers", "name": "Wan2.1 I2V 720P", "size": "14B", "workload": "i2v" },
|
||||
{ "id": "loayrashid/TurboWan2.1-T2V-1.3B-Diffusers", "name": "TurboWan2.1 T2V", "size": "1.3B", "workload": "t2v" },
|
||||
{ "id": "loayrashid/TurboWan2.1-T2V-14B-Diffusers", "name": "TurboWan2.1 T2V", "size": "14B", "workload": "t2v" },
|
||||
{ "id": "loayrashid/TurboWan2.2-I2V-A14B-Diffusers", "name": "TurboWan2.2 I2V", "size": "A14B", "workload": "i2v" },
|
||||
{ "id": "FastVideo/LongCat-Video-T2V-Diffusers", "name": "LongCat T2V", "size": "13.6B", "workload": "t2v" },
|
||||
{ "id": "FastVideo/Matrix-Game-2.0-Base-Diffusers", "name": "Matrix Game 2.0 Base", "size": "1.3B", "workload": "game", "keyboardDim": 4 },
|
||||
{ "id": "FastVideo/Matrix-Game-2.0-GTA-Diffusers", "name": "Matrix Game 2.0 GTA", "size": "1.3B", "workload": "game", "keyboardDim": 2 },
|
||||
{ "id": "FastVideo/Matrix-Game-2.0-TempleRun-Diffusers", "name": "Matrix Game 2.0 TempleRun", "size": "1.3B", "workload": "game", "keyboardDim": 7 }
|
||||
],
|
||||
"runs": [
|
||||
{ "model": "FastVideo/FastWan2.1-T2V-1.3B-Diffusers", "gpu": "rtx5090", "height": 480, "width": 832, "frames": 81, "steps": 40, "attention": "VIDEO_SPARSE_ATTN", "generationSeconds": 22.91, "runtimeSeconds": 139.44 },
|
||||
{ "model": "FastVideo/FastWan2.2-TI2V-5B-FullAttn-Diffusers", "gpu": "rtx5090", "height": 480, "width": 832, "frames": 81, "steps": 40, "attention": "VIDEO_SPARSE_ATTN", "generationSeconds": 17.39, "runtimeSeconds": 116.57 },
|
||||
{ "model": "Wan-AI/Wan2.2-TI2V-5B-Diffusers", "gpu": "rtx5090", "height": 480, "width": 832, "frames": 81, "steps": 40, "attention": "FLASH_ATTN", "generationSeconds": 71.01, "runtimeSeconds": 223.29 },
|
||||
{ "model": "Wan-AI/Wan2.2-T2V-A14B-Diffusers", "gpu": "rtx5090", "height": 480, "width": 832, "frames": 81, "steps": 40, "attention": "FLASH_ATTN", "generationSeconds": 782.09, "runtimeSeconds": 1144.85 },
|
||||
{ "model": "Wan-AI/Wan2.2-I2V-A14B-Diffusers", "gpu": "rtx5090", "height": 480, "width": 832, "frames": 81, "steps": 40, "attention": "FLASH_ATTN", "generationSeconds": 827.48, "runtimeSeconds": 1169.64 },
|
||||
{ "model": "hunyuanvideo-community/HunyuanVideo", "gpu": "rtx5090", "height": 480, "width": 832, "frames": 81, "steps": 40, "attention": "FLASH_ATTN", "generationSeconds": 575.39, "runtimeSeconds": 713.74 },
|
||||
{ "model": "FastVideo/FastHunyuan-diffusers", "gpu": "rtx5090", "height": 720, "width": 1280, "frames": 81, "steps": 50, "attention": "FLASH_ATTN", "generationSeconds": 1389.71, "runtimeSeconds": 1492.36 },
|
||||
{ "model": "Wan-AI/Wan2.1-T2V-1.3B-Diffusers", "gpu": "rtx5090", "height": 480, "width": 832, "frames": 81, "steps": 40, "attention": "FLASH_ATTN", "generationSeconds": 155.86, "runtimeSeconds": 227.07 },
|
||||
{ "model": "Wan-AI/Wan2.1-T2V-14B-Diffusers", "gpu": "rtx5090", "height": 480, "width": 832, "frames": 81, "steps": 40, "attention": "FLASH_ATTN", "generationSeconds": 780.44, "runtimeSeconds": 954.84 },
|
||||
{ "model": "Wan-AI/Wan2.1-I2V-14B-480P-Diffusers", "gpu": "rtx5090", "height": 480, "width": 832, "frames": 81, "steps": 40, "attention": "FLASH_ATTN", "generationSeconds": 842.11, "runtimeSeconds": 1058.56 },
|
||||
{ "model": "Wan-AI/Wan2.1-I2V-14B-720P-Diffusers", "gpu": "rtx5090", "height": 720, "width": 1280, "frames": 81, "steps": 40, "attention": "FLASH_ATTN", "generationSeconds": 2832.76, "runtimeSeconds": 3026.41 },
|
||||
{ "model": "loayrashid/TurboWan2.1-T2V-1.3B-Diffusers", "gpu": "rtx5090", "height": 480, "width": 832, "frames": 81, "steps": 4, "attention": "SLA_ATTN", "generationSeconds": 16.16, "runtimeSeconds": 92.77 },
|
||||
{ "model": "loayrashid/TurboWan2.1-T2V-14B-Diffusers", "gpu": "rtx5090", "height": 480, "width": 832, "frames": 81, "steps": 4, "attention": "SLA_ATTN", "generationSeconds": 60.35, "runtimeSeconds": 604.26 },
|
||||
{ "model": "loayrashid/TurboWan2.2-I2V-A14B-Diffusers", "gpu": "rtx5090", "height": 480, "width": 832, "frames": 81, "steps": 4, "attention": "SLA_ATTN", "runtimeSeconds": 364.0 },
|
||||
{ "model": "FastVideo/LongCat-Video-T2V-Diffusers", "gpu": "rtx5090", "height": 480, "width": 832, "frames": 93, "steps": 40, "attention": "FLASH_ATTN", "generationSeconds": 915.89, "runtimeSeconds": 1061.24 },
|
||||
{ "model": "FastVideo/Matrix-Game-2.0-Base-Diffusers", "gpu": "rtx5090", "height": 352, "width": 640, "frames": 81, "steps": 3, "attention": "FLASH_ATTN", "generationSeconds": 12.29, "runtimeSeconds": 247.2 },
|
||||
{ "model": "FastVideo/Matrix-Game-2.0-GTA-Diffusers", "gpu": "rtx5090", "height": 352, "width": 640, "frames": 81, "steps": 3, "attention": "FLASH_ATTN", "generationSeconds": 13.03, "runtimeSeconds": 212.37 },
|
||||
{ "model": "FastVideo/Matrix-Game-2.0-TempleRun-Diffusers", "gpu": "rtx5090", "height": 352, "width": 640, "frames": 81, "steps": 3, "attention": "FLASH_ATTN", "generationSeconds": 12.85, "runtimeSeconds": 176.79 },
|
||||
{ "model": "FastVideo/FastWan2.1-T2V-1.3B-Diffusers", "gpu": "rtx4090", "height": 480, "width": 832, "frames": 81, "steps": 3, "attention": "VIDEO_SPARSE_ATTN", "generationSeconds": 32.42 },
|
||||
{ "model": "FastVideo/FastWan2.2-TI2V-5B-FullAttn-Diffusers", "gpu": "rtx4090", "height": 480, "width": 832, "frames": 81, "steps": 3, "attention": "VIDEO_SPARSE_ATTN", "generationSeconds": 22.78 },
|
||||
{ "model": "FastVideo/FastWan2.2-TI2V-5B-FullAttn-Diffusers", "gpu": "rtx4090", "height": 480, "width": 832, "frames": 81, "steps": 3, "attention": "FLASH_ATTN", "generationSeconds": 17.81 },
|
||||
{ "model": "Wan-AI/Wan2.1-T2V-1.3B-Diffusers", "gpu": "rtx4090", "height": 480, "width": 832, "frames": 81, "steps": 3, "attention": "FLASH_ATTN", "generationSeconds": 28.62 },
|
||||
{ "model": "Wan-AI/Wan2.1-T2V-1.3B-Diffusers", "gpu": "rtx4090", "height": 480, "width": 832, "frames": 81, "steps": 3, "attention": "SAGE_ATTN", "generationSeconds": 24.62 },
|
||||
{ "model": "loayrashid/TurboWan2.1-T2V-1.3B-Diffusers", "gpu": "rtx4090", "height": 480, "width": 832, "frames": 81, "steps": 3, "attention": "SLA_ATTN", "generationSeconds": 20.13 },
|
||||
{ "model": "FastVideo/Matrix-Game-2.0-Base-Diffusers", "gpu": "rtx4090", "height": 480, "width": 832, "frames": 81, "steps": 3, "attention": "FLASH_ATTN", "generationSeconds": 23.81 },
|
||||
{ "model": "FastVideo/Matrix-Game-2.0-GTA-Diffusers", "gpu": "rtx4090", "height": 480, "width": 832, "frames": 81, "steps": 3, "attention": "FLASH_ATTN", "generationSeconds": 24.24 },
|
||||
{ "model": "FastVideo/Matrix-Game-2.0-TempleRun-Diffusers", "gpu": "rtx4090", "height": 480, "width": 832, "frames": 81, "steps": 3, "attention": "FLASH_ATTN", "generationSeconds": 23.38 }
|
||||
{
|
||||
"id": "FastVideo/FastWan2.1-T2V-1.3B-Diffusers",
|
||||
"name": "FastWan2.1 T2V",
|
||||
"size": "1.3B",
|
||||
"workload": "t2v",
|
||||
"recipe": { "height": 448, "width": 832, "numFrames": 61, "fps": 16, "numInferenceSteps": 3, "guidanceScale": 3, "guidanceScale2": null, "embeddedCfgScale": 6, "flowShift": 8, "boundaryRatio": null, "dmdDenoisingSteps": [1000, 757, 522], "attentionBackends": ["VIDEO_SPARSE_ATTN", "FLASH_ATTN"], "defaultAttentionBackend": "VIDEO_SPARSE_ATTN", "vsaSparsity": 0.8 }
|
||||
},
|
||||
{
|
||||
"id": "FastVideo/FastWan2.2-TI2V-5B-FullAttn-Diffusers",
|
||||
"name": "FastWan2.2 TI2V FullAttn",
|
||||
"size": "5B",
|
||||
"workload": "ti2v",
|
||||
"recipe": { "height": 704, "width": 1280, "numFrames": 121, "fps": 24, "numInferenceSteps": 3, "guidanceScale": 5, "guidanceScale2": null, "embeddedCfgScale": 6, "flowShift": 5, "boundaryRatio": null, "dmdDenoisingSteps": [1000, 757, 522], "attentionBackends": ["FLASH_ATTN", "VIDEO_SPARSE_ATTN"], "defaultAttentionBackend": "FLASH_ATTN", "vsaSparsity": 0 }
|
||||
},
|
||||
{
|
||||
"id": "Wan-AI/Wan2.2-TI2V-5B-Diffusers",
|
||||
"name": "Wan2.2 TI2V",
|
||||
"size": "5B",
|
||||
"workload": "ti2v",
|
||||
"recipe": { "height": 704, "width": 1280, "numFrames": 121, "fps": 24, "numInferenceSteps": 50, "guidanceScale": 5, "guidanceScale2": null, "embeddedCfgScale": 6, "flowShift": 5, "boundaryRatio": null, "dmdDenoisingSteps": null, "attentionBackends": ["FLASH_ATTN", "SAGE_ATTN"], "defaultAttentionBackend": "FLASH_ATTN", "vsaSparsity": 0 }
|
||||
},
|
||||
{
|
||||
"id": "Wan-AI/Wan2.2-T2V-A14B-Diffusers",
|
||||
"name": "Wan2.2 T2V",
|
||||
"size": "A14B",
|
||||
"workload": "t2v",
|
||||
"recipe": { "height": 720, "width": 1280, "numFrames": 81, "fps": 16, "numInferenceSteps": 40, "guidanceScale": 4, "guidanceScale2": 3, "embeddedCfgScale": 6, "flowShift": 12, "boundaryRatio": 0.875, "dmdDenoisingSteps": null, "attentionBackends": ["FLASH_ATTN", "SAGE_ATTN"], "defaultAttentionBackend": "FLASH_ATTN", "vsaSparsity": 0 }
|
||||
},
|
||||
{
|
||||
"id": "Wan-AI/Wan2.2-I2V-A14B-Diffusers",
|
||||
"name": "Wan2.2 I2V",
|
||||
"size": "A14B",
|
||||
"workload": "i2v",
|
||||
"recipe": { "height": 832, "width": 480, "numFrames": 81, "fps": 16, "numInferenceSteps": 40, "guidanceScale": 3.5, "guidanceScale2": 3.5, "embeddedCfgScale": 6, "flowShift": 5, "boundaryRatio": 0.9, "dmdDenoisingSteps": null, "attentionBackends": ["FLASH_ATTN", "SAGE_ATTN"], "defaultAttentionBackend": "FLASH_ATTN", "vsaSparsity": 0 }
|
||||
},
|
||||
{
|
||||
"id": "hunyuanvideo-community/HunyuanVideo",
|
||||
"name": "HunyuanVideo",
|
||||
"size": "13B",
|
||||
"workload": "t2v",
|
||||
"recipe": { "height": 720, "width": 1280, "numFrames": 125, "fps": 24, "numInferenceSteps": 50, "guidanceScale": 1, "guidanceScale2": null, "embeddedCfgScale": 6, "flowShift": 7, "boundaryRatio": null, "dmdDenoisingSteps": null, "attentionBackends": ["FLASH_ATTN", "SAGE_ATTN"], "defaultAttentionBackend": "FLASH_ATTN", "vsaSparsity": 0 }
|
||||
},
|
||||
{
|
||||
"id": "FastVideo/FastHunyuan-diffusers",
|
||||
"name": "FastHunyuan",
|
||||
"size": "13B",
|
||||
"workload": "t2v",
|
||||
"recipe": { "height": 720, "width": 1280, "numFrames": 125, "fps": 24, "numInferenceSteps": 6, "guidanceScale": 1, "guidanceScale2": null, "embeddedCfgScale": 6, "flowShift": 17, "boundaryRatio": null, "dmdDenoisingSteps": null, "attentionBackends": ["FLASH_ATTN", "SAGE_ATTN"], "defaultAttentionBackend": "FLASH_ATTN", "vsaSparsity": 0 }
|
||||
},
|
||||
{
|
||||
"id": "Wan-AI/Wan2.1-T2V-1.3B-Diffusers",
|
||||
"name": "Wan2.1 T2V",
|
||||
"size": "1.3B",
|
||||
"workload": "t2v",
|
||||
"recipe": { "height": 480, "width": 832, "numFrames": 81, "fps": 16, "numInferenceSteps": 50, "guidanceScale": 3, "guidanceScale2": null, "embeddedCfgScale": 6, "flowShift": 3, "boundaryRatio": null, "dmdDenoisingSteps": null, "attentionBackends": ["FLASH_ATTN", "SAGE_ATTN"], "defaultAttentionBackend": "FLASH_ATTN", "vsaSparsity": 0 }
|
||||
},
|
||||
{
|
||||
"id": "Wan-AI/Wan2.1-T2V-14B-Diffusers",
|
||||
"name": "Wan2.1 T2V",
|
||||
"size": "14B",
|
||||
"workload": "t2v",
|
||||
"recipe": { "height": 720, "width": 1280, "numFrames": 81, "fps": 16, "numInferenceSteps": 50, "guidanceScale": 5, "guidanceScale2": null, "embeddedCfgScale": 6, "flowShift": 5, "boundaryRatio": null, "dmdDenoisingSteps": null, "attentionBackends": ["FLASH_ATTN", "SAGE_ATTN"], "defaultAttentionBackend": "FLASH_ATTN", "vsaSparsity": 0 }
|
||||
},
|
||||
{
|
||||
"id": "Wan-AI/Wan2.1-I2V-14B-480P-Diffusers",
|
||||
"name": "Wan2.1 I2V 480P",
|
||||
"size": "14B",
|
||||
"workload": "i2v",
|
||||
"recipe": { "height": 480, "width": 832, "numFrames": 81, "fps": 16, "numInferenceSteps": 40, "guidanceScale": 5, "guidanceScale2": null, "embeddedCfgScale": 6, "flowShift": 3, "boundaryRatio": null, "dmdDenoisingSteps": null, "attentionBackends": ["FLASH_ATTN", "SAGE_ATTN"], "defaultAttentionBackend": "FLASH_ATTN", "vsaSparsity": 0 }
|
||||
},
|
||||
{
|
||||
"id": "Wan-AI/Wan2.1-I2V-14B-720P-Diffusers",
|
||||
"name": "Wan2.1 I2V 720P",
|
||||
"size": "14B",
|
||||
"workload": "i2v",
|
||||
"recipe": { "height": 720, "width": 1280, "numFrames": 81, "fps": 16, "numInferenceSteps": 40, "guidanceScale": 5, "guidanceScale2": null, "embeddedCfgScale": 6, "flowShift": 5, "boundaryRatio": null, "dmdDenoisingSteps": null, "attentionBackends": ["FLASH_ATTN", "SAGE_ATTN"], "defaultAttentionBackend": "FLASH_ATTN", "vsaSparsity": 0 }
|
||||
},
|
||||
{
|
||||
"id": "loayrashid/TurboWan2.1-T2V-1.3B-Diffusers",
|
||||
"name": "TurboWan2.1 T2V",
|
||||
"size": "1.3B",
|
||||
"workload": "t2v",
|
||||
"recipe": { "height": 480, "width": 832, "numFrames": 81, "fps": 16, "numInferenceSteps": 4, "guidanceScale": 1, "guidanceScale2": null, "embeddedCfgScale": 6, "flowShift": 3, "boundaryRatio": null, "dmdDenoisingSteps": null, "attentionBackends": ["SLA_ATTN"], "defaultAttentionBackend": "SLA_ATTN", "vsaSparsity": 0 }
|
||||
},
|
||||
{
|
||||
"id": "loayrashid/TurboWan2.1-T2V-14B-Diffusers",
|
||||
"name": "TurboWan2.1 T2V",
|
||||
"size": "14B",
|
||||
"workload": "t2v",
|
||||
"recipe": { "height": 720, "width": 1280, "numFrames": 81, "fps": 16, "numInferenceSteps": 4, "guidanceScale": 1, "guidanceScale2": null, "embeddedCfgScale": 6, "flowShift": 5, "boundaryRatio": null, "dmdDenoisingSteps": null, "attentionBackends": ["SLA_ATTN"], "defaultAttentionBackend": "SLA_ATTN", "vsaSparsity": 0 }
|
||||
},
|
||||
{
|
||||
"id": "loayrashid/TurboWan2.2-I2V-A14B-Diffusers",
|
||||
"name": "TurboWan2.2 I2V",
|
||||
"size": "A14B",
|
||||
"workload": "i2v",
|
||||
"recipe": { "height": 720, "width": 1280, "numFrames": 81, "fps": 16, "numInferenceSteps": 4, "guidanceScale": 1, "guidanceScale2": null, "embeddedCfgScale": 6, "flowShift": 5, "boundaryRatio": 0.9, "dmdDenoisingSteps": null, "attentionBackends": ["SLA_ATTN"], "defaultAttentionBackend": "SLA_ATTN", "vsaSparsity": 0 }
|
||||
},
|
||||
{
|
||||
"id": "FastVideo/LongCat-Video-T2V-Diffusers",
|
||||
"name": "LongCat T2V",
|
||||
"size": "13.6B",
|
||||
"workload": "t2v",
|
||||
"recipe": { "height": 480, "width": 848, "numFrames": 121, "fps": 24, "numInferenceSteps": 50, "guidanceScale": 1, "guidanceScale2": null, "embeddedCfgScale": 6, "flowShift": null, "boundaryRatio": null, "dmdDenoisingSteps": null, "attentionBackends": ["FLASH_ATTN"], "defaultAttentionBackend": "FLASH_ATTN", "vsaSparsity": 0 }
|
||||
},
|
||||
{
|
||||
"id": "FastVideo/Matrix-Game-2.0-Base-Distilled-Diffusers",
|
||||
"name": "Matrix Game 2.0 Base",
|
||||
"size": "1.3B",
|
||||
"workload": "game",
|
||||
"keyboardDim": 4,
|
||||
"recipe": { "height": 352, "width": 640, "numFrames": 57, "fps": 25, "numInferenceSteps": 3, "guidanceScale": 1, "guidanceScale2": null, "embeddedCfgScale": 6, "flowShift": 5, "boundaryRatio": null, "dmdDenoisingSteps": [1000, 666, 333], "attentionBackends": ["FLASH_ATTN"], "defaultAttentionBackend": "FLASH_ATTN", "vsaSparsity": 0 }
|
||||
},
|
||||
{
|
||||
"id": "FastVideo/Matrix-Game-2.0-GTA-Distilled-Diffusers",
|
||||
"name": "Matrix Game 2.0 GTA",
|
||||
"size": "1.3B",
|
||||
"workload": "game",
|
||||
"keyboardDim": 2,
|
||||
"recipe": { "height": 352, "width": 640, "numFrames": 57, "fps": 25, "numInferenceSteps": 3, "guidanceScale": 1, "guidanceScale2": null, "embeddedCfgScale": 6, "flowShift": 5, "boundaryRatio": null, "dmdDenoisingSteps": [1000, 666, 333], "attentionBackends": ["FLASH_ATTN"], "defaultAttentionBackend": "FLASH_ATTN", "vsaSparsity": 0 }
|
||||
},
|
||||
{
|
||||
"id": "FastVideo/Matrix-Game-2.0-TempleRun-Distilled-Diffusers",
|
||||
"name": "Matrix Game 2.0 TempleRun",
|
||||
"size": "1.3B",
|
||||
"workload": "game",
|
||||
"keyboardDim": 7,
|
||||
"usesMouse": false,
|
||||
"recipe": { "height": 352, "width": 640, "numFrames": 57, "fps": 25, "numInferenceSteps": 3, "guidanceScale": 1, "guidanceScale2": null, "embeddedCfgScale": 6, "flowShift": 5, "boundaryRatio": null, "dmdDenoisingSteps": [1000, 666, 333], "attentionBackends": ["FLASH_ATTN"], "defaultAttentionBackend": "FLASH_ATTN", "vsaSparsity": 0 }
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ const nextConfig = {
|
||||
output: "export",
|
||||
trailingSlash: true,
|
||||
basePath,
|
||||
assetPrefix: basePath,
|
||||
typescript: {
|
||||
ignoreBuildErrors: false,
|
||||
},
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"packageManager": "pnpm@10.28.0",
|
||||
"scripts": {
|
||||
"dev": "next dev -p 3003",
|
||||
"build": "next build"
|
||||
"build": "node scripts/validate-data.mjs && next build"
|
||||
},
|
||||
"dependencies": {
|
||||
"lucide-react": "^0.564.0",
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
import assert from "node:assert/strict"
|
||||
import { readFile } from "node:fs/promises"
|
||||
|
||||
const load = async (name) => JSON.parse(await readFile(new URL(`../data/${name}`, import.meta.url), "utf8"))
|
||||
const [quickstart, tuning] = await Promise.all([load("quickstart.json"), load("tuning.json")])
|
||||
|
||||
assert.match(tuning.source.fastvideoCommit, /^[0-9a-f]{40}$/)
|
||||
|
||||
const backendIds = new Set(tuning.attentionBackends.map(({ id }) => id))
|
||||
const workloadIds = new Set(tuning.workloads.map(({ id }) => id))
|
||||
const modelIds = new Set()
|
||||
for (const model of tuning.models) {
|
||||
assert(!modelIds.has(model.id), `duplicate model: ${model.id}`)
|
||||
modelIds.add(model.id)
|
||||
assert(workloadIds.has(model.workload), `${model.id}: unknown workload ${model.workload}`)
|
||||
|
||||
const { recipe } = model
|
||||
for (const key of ["height", "width", "numFrames", "fps", "numInferenceSteps"]) {
|
||||
assert(Number.isInteger(recipe[key]) && recipe[key] > 0, `${model.id}: invalid ${key}`)
|
||||
}
|
||||
if (model.workload === "game") {
|
||||
assert(recipe.numFrames % 12 === 9, `${model.id}: Matrix frames must be 9 + 12k`)
|
||||
}
|
||||
assert(recipe.guidanceScale > 0, `${model.id}: guidance must be positive`)
|
||||
assert(recipe.vsaSparsity >= 0 && recipe.vsaSparsity <= 1, `${model.id}: invalid VSA sparsity`)
|
||||
if (recipe.dmdDenoisingSteps !== null) {
|
||||
assert(recipe.dmdDenoisingSteps.length > 0 &&
|
||||
recipe.dmdDenoisingSteps.every((step) => Number.isInteger(step) && step > 0),
|
||||
`${model.id}: invalid DMD schedule`)
|
||||
}
|
||||
assert(recipe.attentionBackends.length > 0, `${model.id}: no attention backend`)
|
||||
assert(recipe.attentionBackends.includes(recipe.defaultAttentionBackend), `${model.id}: invalid default backend`)
|
||||
for (const backend of recipe.attentionBackends) {
|
||||
assert(backendIds.has(backend), `${model.id}: unknown backend ${backend}`)
|
||||
}
|
||||
}
|
||||
|
||||
assert(modelIds.has(tuning.defaults.model_id), "unknown default model")
|
||||
const profileKeys = new Set()
|
||||
for (const profile of quickstart.profiles) {
|
||||
assert(modelIds.has(profile.model), `quick-start profile uses unknown model: ${profile.model}`)
|
||||
assert(tuning.models.find(({ id }) => id === profile.model).workload === profile.task,
|
||||
`${profile.model}: quick-start task does not match recipe workload`)
|
||||
const key = `${profile.task}:${profile.tier}`
|
||||
assert(!profileKeys.has(key), `duplicate quick-start profile: ${key}`)
|
||||
profileKeys.add(key)
|
||||
}
|
||||
|
||||
const unsupportedClaims = /"(?:generationSeconds|runtimeSeconds|timeSec|firstRunSec|vramMin|ramMin)"/
|
||||
assert(!unsupportedClaims.test(JSON.stringify({ quickstart, tuning })), "unproven performance claim in recipe data")
|
||||
|
||||
console.log(`Validated ${tuning.models.length} recipes and ${quickstart.profiles.length} quick-start profiles.`)
|
||||
+4
-4
@@ -3,10 +3,10 @@
|
||||
This directory contains the FastVideo documentation built with MkDocs.
|
||||
|
||||
The Quick Start and Advanced Tuning pages embed an interactive **config
|
||||
generator** — a separate Next.js app in [`consumer-guide/`](../consumer-guide/)
|
||||
that is built independently and copied into the docs site under
|
||||
`/config-generator/`. To work on that app itself, see
|
||||
[`consumer-guide/README.md`](../consumer-guide/README.md).
|
||||
generator** — a separate Next.js app documented in
|
||||
[`consumer-guide/README.md`](../consumer-guide/README.md). It is built
|
||||
independently and copied into the docs artifact under `config-generator/`. Its
|
||||
asset URLs use the GitHub Pages base path reported by `actions/configure-pages`.
|
||||
|
||||
## Build the docs locally
|
||||
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
(() => {
|
||||
const resizeType = "fastvideo-config-generator:resize";
|
||||
|
||||
window.addEventListener("message", (event) => {
|
||||
if (event.origin !== window.location.origin) return;
|
||||
if (!event.data || typeof event.data !== "object" || event.data.type !== resizeType) return;
|
||||
|
||||
const frame = Array.from(document.querySelectorAll("iframe[data-config-generator]"))
|
||||
.find((candidate) => candidate.contentWindow === event.source);
|
||||
const height = Number(event.data.height);
|
||||
if (!frame || !Number.isFinite(height) || height < 320 || height > 20000) return;
|
||||
|
||||
frame.style.height = `${Math.ceil(height)}px`;
|
||||
});
|
||||
})();
|
||||
@@ -62,11 +62,11 @@ img {
|
||||
}
|
||||
|
||||
.adv-tuning-guide-wrap {
|
||||
width: calc(100vw - 26rem);
|
||||
width: 100%;
|
||||
max-width: none;
|
||||
overflow: hidden;
|
||||
background: #fff;
|
||||
margin-right: 1rem;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.adv-tuning-guide-frame {
|
||||
|
||||
@@ -1,21 +1,14 @@
|
||||
---
|
||||
hide:
|
||||
- toc
|
||||
- toc
|
||||
---
|
||||
|
||||
<div class="adv-tuning-guide-wrap">
|
||||
<iframe
|
||||
class="adv-tuning-guide-frame"
|
||||
src="/config-generator/tuning/"
|
||||
src="../../config-generator/tuning/"
|
||||
title="FastVideo Advanced Tuning Guide"
|
||||
data-config-generator
|
||||
loading="lazy"
|
||||
></iframe>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
window.addEventListener("message", (e) => {
|
||||
if (e.data && e.data.type === "adv-tuning-guide-height") {
|
||||
const frame = document.querySelector(".adv-tuning-guide-frame");
|
||||
if (frame) frame.style.height = e.data.height + "px";
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -68,5 +68,5 @@ uv pip install flash-attn --no-build-isolation -v
|
||||
Now that FastVideo is installed, head to the [Quick Start](quick_start.md) to generate your first video.
|
||||
|
||||
!!! tip "Not sure which command to run?"
|
||||
- The [Quick Start](quick_start.md) page has an interactive Config Generator. Select your task and hardware to get a ready-to-copy `fastvideo generate` command instantly.
|
||||
- For fine-grained control over all parameters, use the [Advanced Tuning Guide](advanced_tuning_guide.md).
|
||||
- The [Quick Start](quick_start.md) page has an interactive Config Generator. Select your task, maintained model profile, and GPU count to get a ready-to-copy `fastvideo generate` command.
|
||||
- For fine-grained control over all parameters, use the [Advanced Tuning Guide](advanced_tuning_guide.md).
|
||||
|
||||
@@ -25,83 +25,21 @@ uv pip install flash-attn --no-build-isolation -v
|
||||
|
||||
## ⚡ Generate Your Command
|
||||
|
||||
Select your task and hardware to get a ready-to-run command:
|
||||
Select your task, model profile, and GPU count to get a ready-to-run command:
|
||||
|
||||
<div class="quick-start-guide-wrap">
|
||||
<iframe
|
||||
class="quick-start-guide-frame"
|
||||
src="/config-generator/"
|
||||
src="../../config-generator/"
|
||||
title="FastVideo Guided Config Generator"
|
||||
data-config-generator
|
||||
loading="lazy"
|
||||
></iframe>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
window.addEventListener("message", (e) => {
|
||||
if (e.data && e.data.type === "quick-start-guide-height") {
|
||||
const frame = document.querySelector(".quick-start-guide-frame");
|
||||
if (frame) frame.style.height = e.data.height + "px";
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
!!! tip "Need more control?"
|
||||
Use the [Advanced Tuning Guide](advanced_tuning_guide.md) to tune all parameters — resolution, attention backend, memory offloading, and more.
|
||||
|
||||
## Python API
|
||||
|
||||
Prefer Python over the CLI? Here are equivalent examples:
|
||||
|
||||
### Text-to-Video Generation
|
||||
|
||||
```python
|
||||
from fastvideo import VideoGenerator
|
||||
|
||||
def main():
|
||||
# Create a video generator with a pre-trained model
|
||||
generator = VideoGenerator.from_pretrained(
|
||||
"Wan-AI/Wan2.1-T2V-1.3B-Diffusers",
|
||||
num_gpus=1, # Adjust based on your hardware
|
||||
)
|
||||
|
||||
# Define a prompt for your video
|
||||
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
|
||||
)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
```
|
||||
|
||||
### Image-to-Video Generation
|
||||
|
||||
```python
|
||||
from fastvideo import VideoGenerator, SamplingParam
|
||||
|
||||
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)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
```
|
||||
|
||||
## Next Steps
|
||||
|
||||
- [Advanced Tuning Guide](advanced_tuning_guide.md) - Fine-grained parameter tuning
|
||||
|
||||
+2
-1
@@ -78,7 +78,7 @@ plugins:
|
||||
minify_js: true
|
||||
minify_css: true
|
||||
cache_safe: true
|
||||
js_files: [assets/copy-page.js]
|
||||
js_files: [assets/copy-page.js, assets/config-generator.js]
|
||||
css_files: [assets/custom.css]
|
||||
- api-autonav:
|
||||
modules: ["fastvideo"]
|
||||
@@ -238,3 +238,4 @@ extra_css:
|
||||
# Custom JavaScript
|
||||
extra_javascript:
|
||||
- assets/copy-page.js
|
||||
- assets/config-generator.js
|
||||
|
||||
Reference in New Issue
Block a user