diff --git a/consumer-guide/.gitignore b/consumer-guide/.gitignore deleted file mode 100644 index 9b04f643a..000000000 --- a/consumer-guide/.gitignore +++ /dev/null @@ -1,17 +0,0 @@ -# v0 sandbox internal files -__v0_runtime_loader.js -__v0_devtools.tsx -__v0_jsx-dev-runtime.ts -.snowflake/ -.v0-trash/ -.vercel/ -next.user-config.* - -# Environment variables -.env*.local - -# Common ignores -node_modules -.next/ -.DS_Store -.vercel diff --git a/consumer-guide/README.md b/consumer-guide/README.md deleted file mode 100644 index f11272311..000000000 --- a/consumer-guide/README.md +++ /dev/null @@ -1,29 +0,0 @@ -# FastVideo Consumer Guide - -A standalone Next.js consumer guide for FastVideo configuration selection and advanced tuning. - -## Requirements - -- Node.js 20 or newer -- pnpm - -## Run Locally - -```bash -pnpm install -pnpm dev -``` - -Then open http://localhost:3000. - -## Build - -```bash -pnpm build -pnpm start -``` - -## Notes - -This app is independent from the main FastVideo Python package. -Run commands from this `consumer-guide/` directory. diff --git a/consumer-guide/app/globals.css b/consumer-guide/app/globals.css deleted file mode 100644 index dc2aea17f..000000000 --- a/consumer-guide/app/globals.css +++ /dev/null @@ -1,125 +0,0 @@ -@import 'tailwindcss'; -@import 'tw-animate-css'; - -@custom-variant dark (&:is(.dark *)); - -:root { - --background: oklch(1 0 0); - --foreground: oklch(0.145 0 0); - --card: oklch(1 0 0); - --card-foreground: oklch(0.145 0 0); - --popover: oklch(1 0 0); - --popover-foreground: oklch(0.145 0 0); - --primary: oklch(0.205 0 0); - --primary-foreground: oklch(0.985 0 0); - --secondary: oklch(0.97 0 0); - --secondary-foreground: oklch(0.205 0 0); - --muted: oklch(0.97 0 0); - --muted-foreground: oklch(0.556 0 0); - --accent: oklch(0.97 0 0); - --accent-foreground: oklch(0.205 0 0); - --destructive: oklch(0.577 0.245 27.325); - --destructive-foreground: oklch(0.577 0.245 27.325); - --border: oklch(0.922 0 0); - --input: oklch(0.922 0 0); - --ring: oklch(0.708 0 0); - --chart-1: oklch(0.646 0.222 41.116); - --chart-2: oklch(0.6 0.118 184.704); - --chart-3: oklch(0.398 0.07 227.392); - --chart-4: oklch(0.828 0.189 84.429); - --chart-5: oklch(0.769 0.188 70.08); - --radius: 0.625rem; - --sidebar: oklch(0.985 0 0); - --sidebar-foreground: oklch(0.145 0 0); - --sidebar-primary: oklch(0.205 0 0); - --sidebar-primary-foreground: oklch(0.985 0 0); - --sidebar-accent: oklch(0.97 0 0); - --sidebar-accent-foreground: oklch(0.205 0 0); - --sidebar-border: oklch(0.922 0 0); - --sidebar-ring: oklch(0.708 0 0); -} - -.dark { - --background: oklch(0.145 0 0); - --foreground: oklch(0.985 0 0); - --card: oklch(0.145 0 0); - --card-foreground: oklch(0.985 0 0); - --popover: oklch(0.145 0 0); - --popover-foreground: oklch(0.985 0 0); - --primary: oklch(0.985 0 0); - --primary-foreground: oklch(0.205 0 0); - --secondary: oklch(0.269 0 0); - --secondary-foreground: oklch(0.985 0 0); - --muted: oklch(0.269 0 0); - --muted-foreground: oklch(0.708 0 0); - --accent: oklch(0.269 0 0); - --accent-foreground: oklch(0.985 0 0); - --destructive: oklch(0.396 0.141 25.723); - --destructive-foreground: oklch(0.637 0.237 25.331); - --border: oklch(0.269 0 0); - --input: oklch(0.269 0 0); - --ring: oklch(0.439 0 0); - --chart-1: oklch(0.488 0.243 264.376); - --chart-2: oklch(0.696 0.17 162.48); - --chart-3: oklch(0.769 0.188 70.08); - --chart-4: oklch(0.627 0.265 303.9); - --chart-5: oklch(0.645 0.246 16.439); - --sidebar: oklch(0.205 0 0); - --sidebar-foreground: oklch(0.985 0 0); - --sidebar-primary: oklch(0.488 0.243 264.376); - --sidebar-primary-foreground: oklch(0.985 0 0); - --sidebar-accent: oklch(0.269 0 0); - --sidebar-accent-foreground: oklch(0.985 0 0); - --sidebar-border: oklch(0.269 0 0); - --sidebar-ring: oklch(0.439 0 0); -} - -@theme inline { - --font-sans: 'Geist', 'Geist Fallback'; - --font-mono: 'Geist Mono', 'Geist Mono Fallback'; - --color-background: var(--background); - --color-foreground: var(--foreground); - --color-card: var(--card); - --color-card-foreground: var(--card-foreground); - --color-popover: var(--popover); - --color-popover-foreground: var(--popover-foreground); - --color-primary: var(--primary); - --color-primary-foreground: var(--primary-foreground); - --color-secondary: var(--secondary); - --color-secondary-foreground: var(--secondary-foreground); - --color-muted: var(--muted); - --color-muted-foreground: var(--muted-foreground); - --color-accent: var(--accent); - --color-accent-foreground: var(--accent-foreground); - --color-destructive: var(--destructive); - --color-destructive-foreground: var(--destructive-foreground); - --color-border: var(--border); - --color-input: var(--input); - --color-ring: var(--ring); - --color-chart-1: var(--chart-1); - --color-chart-2: var(--chart-2); - --color-chart-3: var(--chart-3); - --color-chart-4: var(--chart-4); - --color-chart-5: var(--chart-5); - --radius-sm: calc(var(--radius) - 4px); - --radius-md: calc(var(--radius) - 2px); - --radius-lg: var(--radius); - --radius-xl: calc(var(--radius) + 4px); - --color-sidebar: var(--sidebar); - --color-sidebar-foreground: var(--sidebar-foreground); - --color-sidebar-primary: var(--sidebar-primary); - --color-sidebar-primary-foreground: var(--sidebar-primary-foreground); - --color-sidebar-accent: var(--sidebar-accent); - --color-sidebar-accent-foreground: var(--sidebar-accent-foreground); - --color-sidebar-border: var(--sidebar-border); - --color-sidebar-ring: var(--sidebar-ring); -} - -@layer base { - * { - @apply border-border outline-ring/50; - } - body { - @apply bg-background text-foreground; - } -} diff --git a/consumer-guide/app/layout.tsx b/consumer-guide/app/layout.tsx deleted file mode 100644 index 91eb9484e..000000000 --- a/consumer-guide/app/layout.tsx +++ /dev/null @@ -1,45 +0,0 @@ -import type { Metadata } from 'next' -import { Geist, Geist_Mono } from 'next/font/google' -import { Analytics } from '@vercel/analytics/next' -import './globals.css' - -const _geist = Geist({ subsets: ["latin"] }); -const _geistMono = Geist_Mono({ subsets: ["latin"] }); - -export const metadata: Metadata = { - title: 'FastVideo Config Selector', - description: 'Choose your hardware and task to get a recommended FastVideo configuration', - generator: 'v0.app', - icons: { - icon: [ - { - url: '/icon-light-32x32.png', - media: '(prefers-color-scheme: light)', - }, - { - url: '/icon-dark-32x32.png', - media: '(prefers-color-scheme: dark)', - }, - { - url: '/icon.svg', - type: 'image/svg+xml', - }, - ], - apple: '/apple-icon.png', - }, -} - -export default function RootLayout({ - children, -}: Readonly<{ - children: React.ReactNode -}>) { - return ( - - - {children} - {process.env.NODE_ENV === 'production' && } - - - ) -} diff --git a/consumer-guide/app/page.tsx b/consumer-guide/app/page.tsx deleted file mode 100644 index 9c147e1ff..000000000 --- a/consumer-guide/app/page.tsx +++ /dev/null @@ -1,334 +0,0 @@ -"use client" - -import { useState, useMemo } from "react" -import { Monitor, Cpu, HardDrive, Layers, Clock, Copy, Check, Film, Image, Sparkles, Gamepad2, Settings2 } from "lucide-react" -import Link from "next/link" - -type Task = "t2v" | "i2v" | "ti2v" | "action" -type Tier = "quick" | "daily" | "best" - -interface Config { - model: string - modelShort: string - attn: string - h: number - w: number - frames: number - steps: number - cfg: number - vramMin: number - ramMin: number - time: string - vram: string - offload: boolean - extra?: string -} - -const CONFIGS: Record> = { - t2v: { - quick: { model: "FastVideo/FastWan2.1-T2V-1.3B-Diffusers", modelShort: "FastWan2.1-T2V-1.3B", attn: "VIDEO_SPARSE_ATTN", h: 480, w: 832, frames: 49, steps: 20, cfg: 5.0, vramMin: 8, ramMin: 16, time: "~60 s", vram: "~16 GB", offload: false }, - daily: { model: "FastVideo/FastWan2.1-T2V-1.3B-Diffusers", modelShort: "FastWan2.1-T2V-1.3B", attn: "FLASH_ATTN", h: 720, w: 1280, frames: 81, steps: 30, cfg: 5.0, vramMin: 20, ramMin: 32, time: "~3 min", vram: "~22 GB", offload: false }, - best: { model: "Wan-AI/Wan2.1-T2V-14B-Diffusers", modelShort: "Wan2.1-T2V-14B", attn: "FLASH_ATTN", h: 720, w: 1280, frames: 81, steps: 50, cfg: 6.0, vramMin: 16, ramMin: 40, time: "~15 min", vram: "~18 GB + ~40 GB RAM", offload: true } - }, - i2v: { - quick: { model: "Wan-AI/Wan2.1-I2V-14B-480P-Diffusers", modelShort: "Wan2.1-I2V-14B-480P", attn: "FLASH_ATTN", h: 480, w: 832, frames: 49, steps: 20, cfg: 5.0, vramMin: 16, ramMin: 32, time: "~2 min", vram: "~18 GB", offload: true, extra: "--image ./input.png" }, - daily: { model: "Wan-AI/Wan2.1-I2V-14B-480P-Diffusers", modelShort: "Wan2.1-I2V-14B-480P", attn: "FLASH_ATTN", h: 480, w: 832, frames: 81, steps: 30, cfg: 5.0, vramMin: 16, ramMin: 32, time: "~5 min", vram: "~20 GB", offload: true, extra: "--image ./input.png" }, - best: { model: "Wan-AI/Wan2.1-I2V-14B-720P-Diffusers", modelShort: "Wan2.1-I2V-14B-720P", attn: "FLASH_ATTN", h: 720, w: 1280, frames: 81, steps: 50, cfg: 6.0, vramMin: 16, ramMin: 40, time: "~20 min", vram: "~20 GB + ~40 GB RAM", offload: true, extra: "--image ./input.png" } - }, - ti2v: { - quick: { model: "FastVideo/FastWan2.2-TI2V-5B-FullAttn-Diffusers", modelShort: "FastWan2.2-TI2V-5B", attn: "FLASH_ATTN", h: 480, w: 832, frames: 49, steps: 20, cfg: 5.0, vramMin: 16, ramMin: 32, time: "~2 min", vram: "~18 GB", offload: false, extra: "--image ./input.png" }, - daily: { model: "FastVideo/FastWan2.2-TI2V-5B-FullAttn-Diffusers", modelShort: "FastWan2.2-TI2V-5B", attn: "FLASH_ATTN", h: 720, w: 1280, frames: 81, steps: 30, cfg: 5.0, vramMin: 20, ramMin: 32, time: "~5 min", vram: "~22 GB", offload: false, extra: "--image ./input.png" }, - best: { model: "Wan-AI/Wan2.2-TI2V-5B-Diffusers", modelShort: "Wan2.2-TI2V-5B", attn: "SAGE_ATTN", h: 720, w: 1280, frames: 81, steps: 50, cfg: 6.0, vramMin: 20, ramMin: 40, time: "~15 min", vram: "~22 GB + ~40 GB RAM", offload: true, extra: "--image ./input.png" } - }, - action: { - quick: { model: "FastVideo/Matrix-Game-2.0-Base-Diffusers", modelShort: "Matrix-Game-2.0-Base", attn: "FLASH_ATTN", h: 480, w: 832, frames: 49, steps: 20, cfg: 5.0, vramMin: 16, ramMin: 32, time: "~2 min", vram: "~18 GB", offload: false, extra: "--image ./input.png --action forward" }, - daily: { model: "FastVideo/Matrix-Game-2.0-Base-Diffusers", modelShort: "Matrix-Game-2.0-Base", attn: "FLASH_ATTN", h: 720, w: 1280, frames: 81, steps: 30, cfg: 5.0, vramMin: 20, ramMin: 32, time: "~5 min", vram: "~22 GB", offload: false, extra: "--image ./input.png --action forward" }, - best: { model: "FastVideo/Matrix-Game-2.0-GTA-Diffusers", modelShort: "Matrix-Game-2.0-GTA", attn: "FLASH_ATTN", h: 720, w: 1280, frames: 81, steps: 50, cfg: 6.0, vramMin: 20, ramMin: 40, time: "~15 min", vram: "~20 GB + ~40 GB RAM", offload: true, extra: "--image ./input.png --action forward" } - } -} - -const TASKS: { id: Task; label: string; sub: string; icon: typeof Film }[] = [ - { 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: "action", label: "Action Control", sub: "Matrix Game", icon: Gamepad2 }, -] - -const TIERS: { id: Tier; name: string; desc: string; badge?: string }[] = [ - { id: "quick", name: "Quick Try", desc: "Fast preview. Lower resolution, fewer steps." }, - { id: "daily", name: "Daily Use", desc: "Balanced quality and speed.", badge: "Recommended" }, - { id: "best", name: "Best Quality", desc: "14B model, max fidelity. Requires offloading." }, -] - -export default function FastVideoConfigSelector() { - const [task, setTask] = useState("t2v") - const [tier, setTier] = useState("daily") - const [gpu, setGpu] = useState("4090") - const [vram, setVram] = useState(24) - const [ram, setRam] = useState(64) - const [ngpu, setNgpu] = useState(1) - const [copied, setCopied] = useState(false) - - const config = CONFIGS[task][tier] - - const warning = useMemo(() => { - 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(() => { - let cmd = `# 1. install\npip install fastvideo\n\n` - cmd += `# 2. download model\nhuggingface-cli download ${config.model} \\\n --local-dir ./models/${config.modelShort}\n\n` - cmd += `# 3. run\nfastvideo generate \\\n` - cmd += ` --model ./models/${config.modelShort} \\\n` - cmd += ` --attention ${config.attn} \\\n` - cmd += ` --height ${config.h} --width ${config.w} \\\n` - cmd += ` --num_frames ${config.frames} \\\n` - cmd += ` --num_inference_steps ${config.steps} \\\n` - cmd += ` --guidance_scale ${config.cfg.toFixed(1)}` - if (config.offload) { - cmd += ` \\\n --dit_cpu_offload \\\n --vae_cpu_offload \\\n --pin_cpu_memory` - } - if (config.extra) { - cmd += ` \\\n ${config.extra}` - } - cmd += ` \\\n --prompt "your prompt here"` - return cmd - }, [config]) - - const copyCommand = async () => { - await navigator.clipboard.writeText(command) - setCopied(true) - setTimeout(() => setCopied(false), 2000) - } - - return ( -
- {/* Header */} -
-
-
-
- FastVideo Logo -
-

Config Selector

-

Choose your hardware and task to get a recommended configuration

-
-
- - - Advanced Tuning - -
-
-
- -
- {/* Step 1: Task Selection */} -
-
- 1 -

What do you want to make?

-
-
- {TASKS.map(({ id, label, sub, icon: Icon }) => ( - - ))} -
-
- - {/* Step 2: Machine Specs */} -
-
- 2 -

Your machine specs

-
-
-
-
- - GPU Model -
- -
-
-
- - VRAM (GB) -
- -
-
-
- - RAM (GB) -
- -
-
-
- - Number of GPUs -
- -
-
-
- - {/* Step 3: Output Mode */} -
-
- 3 -

Output mode

-
-
- {TIERS.map(({ id, name, desc, badge }) => { - const tierConfig = CONFIGS[task][id] - return ( - - ) - })} -
- {warning && ( -
- {warning} -
- )} -
- - {/* Output Configuration */} -
-
- ✓ -

Your configuration

-
-
- {/* Meta Cards */} -
-
-
Model
-
{config.modelShort}
-
-
-
Est. Generation Time
-
{config.time}
-
-
-
Peak VRAM
-
{config.vram}
-
-
- {/* Command Block */} -
- -
-                {command}
-              
-
-
-
-
-
- ) -} diff --git a/consumer-guide/app/tuning/page.tsx b/consumer-guide/app/tuning/page.tsx deleted file mode 100644 index 526002d23..000000000 --- a/consumer-guide/app/tuning/page.tsx +++ /dev/null @@ -1,823 +0,0 @@ -"use client" - -import { useState, useMemo } from "react" -import { - Monitor, Cpu, Film, Sparkles, Zap, HardDrive, BarChart3, - Copy, Check, Info, ChevronDown, ChevronUp, Settings2, - Layers, Clock, Database, Gauge -} from "lucide-react" -import Link from "next/link" - -// Types -interface Config { - // Category A - Model & Hardware - model_id: string - workload_type: string - gpu: string - num_gpus: number - // Category B - Video Spec - height: number - width: number - num_frames: number - fps: number - // Category C - Quality - num_inference_steps: number - guidance_scale: number - embedded_cfg_scale: number - flow_shift: number | null - seed: number - // Category D - Speed - attention_backend: string - VSA_sparsity: number - dmd_denoising_steps: string - // Category E - Memory - dit_cpu_offload: boolean - dit_layerwise_offload: boolean - vae_cpu_offload: boolean - text_encoder_cpu_offload: boolean - image_encoder_cpu_offload: boolean - pin_cpu_memory: boolean - use_fsdp_inference: boolean -} - -const modelOptions = [ - { id: "FastVideo/FastWan2.1-T2V-1.3B-Diffusers", name: "FastWan 1.3B (T2V)", size: "1.3B" }, - { id: "Wan-AI/Wan2.1-T2V-14B-Diffusers", name: "Wan 14B (T2V)", size: "14B" }, - { id: "Wan-AI/Wan2.1-I2V-14B-480P-Diffusers", name: "Wan 14B I2V 480P", size: "14B" }, - { id: "Wan-AI/Wan2.1-I2V-14B-720P-Diffusers", name: "Wan 14B I2V 720P", size: "14B" }, -] - -const workloadOptions = [ - { 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: "action", name: "Action", icon: Zap }, -] - -const gpuOptions = [ - { id: "rtx4090", name: "RTX 4090", vram: "24GB" }, - { id: "rtx5090", name: "RTX 5090", vram: "32GB" }, - { id: "a100", name: "A100", vram: "40/80GB" }, - { id: "h100", name: "H100", vram: "80GB" }, -] - -const resolutionPresets = [ - { height: 480, width: 832, label: "480p (832×480)" }, - { height: 720, width: 1280, label: "720p (1280×720)" }, - { height: 1080, width: 1920, label: "1080p (1920×1080)" }, -] - -const framePresets = [ - { frames: 49, label: "49 frames (~2s @24fps)" }, - { frames: 81, label: "81 frames (~3.4s @24fps)" }, - { frames: 121, label: "121 frames (~5s @24fps)" }, -] - -const attentionBackends = [ - { id: "FLASH_ATTN", name: "Flash Attention", desc: "Best quality-speed trade-off", speed: "Baseline" }, - { id: "VIDEO_SPARSE_ATTN", name: "Video Sparse Attention", desc: "~30% faster, minimal quality loss", speed: "Fast" }, - { id: "SAGE_ATTN", name: "Sage Attention", desc: "~40% faster, visible at high motion", speed: "Faster" }, - { id: "SLA_ATTN", name: "Sliding Tile Attention", desc: "Check model compatibility", speed: "Fast" }, -] - -// Tooltip component -function Tooltip({ content }: { content: string }) { - const [show, setShow] = useState(false) - return ( -
- - {show && ( -
- {content} -
-
- )} -
- ) -} - -// Collapsible section -function Section({ - title, - icon: Icon, - number, - children, - defaultOpen = true, - color = "sky" -}: { - title: string - icon: React.ElementType - number: string - children: React.ReactNode - defaultOpen?: boolean - color?: "sky" | "emerald" | "amber" | "violet" | "rose" | "slate" -}) { - const [open, setOpen] = useState(defaultOpen) - const colorClasses = { - sky: "bg-sky-500/20 text-sky-400", - emerald: "bg-emerald-500/20 text-emerald-400", - amber: "bg-amber-500/20 text-amber-400", - violet: "bg-violet-500/20 text-violet-400", - rose: "bg-rose-500/20 text-rose-400", - slate: "bg-slate-500/20 text-slate-400", - } - const textColors = { - sky: "text-sky-400", - emerald: "text-emerald-400", - amber: "text-amber-400", - violet: "text-violet-400", - rose: "text-rose-400", - slate: "text-slate-400", - } - - return ( -
- - {open &&
{children}
} -
- ) -} - -// Input components -function NumberInput({ - label, - value, - onChange, - min, - max, - step = 1, - tooltip, - unit -}: { - label: string - value: number - onChange: (v: number) => void - min?: number - max?: number - step?: number - tooltip?: string - unit?: string -}) { - return ( -
- -
- onChange(Number(e.target.value))} - min={min} - max={max} - step={step} - className="w-full rounded-lg border border-white/10 bg-slate-900/50 px-3 py-2.5 text-sm text-white focus:border-sky-500/50 focus:outline-none focus:ring-1 focus:ring-sky-500/50" - /> - {unit && {unit}} -
-
- ) -} - -function SelectInput({ - label, - value, - onChange, - options, - tooltip -}: { - label: string - value: string - onChange: (v: string) => void - options: { id: string; name: string; desc?: string }[] - tooltip?: string -}) { - return ( -
- - -
- ) -} - -function Toggle({ - label, - checked, - onChange, - tooltip, - disabled = false -}: { - label: string - checked: boolean - onChange: (v: boolean) => void - tooltip?: string - disabled?: boolean -}) { - return ( - - ) -} - -export default function AdvancedTuningPage() { - const [copied, setCopied] = useState(false) - const [config, setConfig] = useState({ - // Category A - model_id: "FastVideo/FastWan2.1-T2V-1.3B-Diffusers", - workload_type: "t2v", - gpu: "rtx4090", - num_gpus: 1, - // Category B - height: 480, - width: 832, - num_frames: 49, - fps: 24, - // Category C - num_inference_steps: 30, - guidance_scale: 5.0, - embedded_cfg_scale: 6.0, - flow_shift: null, - seed: -1, - // Category D - attention_backend: "FLASH_ATTN", - VSA_sparsity: 0, - dmd_denoising_steps: "1000,757,522", - // Category E - dit_cpu_offload: false, - dit_layerwise_offload: false, - vae_cpu_offload: false, - text_encoder_cpu_offload: false, - image_encoder_cpu_offload: false, - pin_cpu_memory: false, - use_fsdp_inference: false, - }) - - // Derived values - const videoLength = useMemo(() => (config.num_frames / config.fps).toFixed(1), [config.num_frames, config.fps]) - const totalPixels = useMemo(() => config.height * config.width * config.num_frames, [config.height, config.width, config.num_frames]) - const computeCost = useMemo(() => totalPixels * config.num_inference_steps, [totalPixels, config.num_inference_steps]) - - // Estimate generation time (rough approximation) - const estimatedTime = useMemo(() => { - const baseTime = (totalPixels / 19600000) * 60 * (config.num_inference_steps / 30) - let multiplier = 1 - if (config.dit_cpu_offload) multiplier *= 2.5 - if (config.dit_layerwise_offload) multiplier *= 4 - if (config.attention_backend === "VIDEO_SPARSE_ATTN") multiplier *= 0.7 - if (config.attention_backend === "SAGE_ATTN") multiplier *= 0.6 - return Math.round(baseTime * multiplier) - }, [totalPixels, config.num_inference_steps, config.dit_cpu_offload, config.dit_layerwise_offload, config.attention_backend]) - - // Generate command - const command = useMemo(() => { - const lines = [ - "# 1. Install FastVideo", - "pip install fastvideo", - "", - "# 2. Download model", - `huggingface-cli download ${config.model_id} \\`, - ` --local-dir ./models/${config.model_id.split('/').pop()}`, - "", - "# 3. Run generation", - "fastvideo generate \\", - ` --model ./models/${config.model_id.split('/').pop()} \\`, - ` --attention ${config.attention_backend} \\`, - ` --height ${config.height} --width ${config.width} \\`, - ` --num_frames ${config.num_frames} \\`, - ` --num_inference_steps ${config.num_inference_steps} \\`, - ` --guidance_scale ${config.guidance_scale} \\`, - ] - - if (config.embedded_cfg_scale !== 6.0) { - lines.push(` --embedded_cfg_scale ${config.embedded_cfg_scale} \\`) - } - if (config.flow_shift !== null) { - lines.push(` --flow_shift ${config.flow_shift} \\`) - } - if (config.seed !== -1) { - lines.push(` --seed ${config.seed} \\`) - } - if (config.attention_backend === "VIDEO_SPARSE_ATTN" && config.VSA_sparsity > 0) { - lines.push(` --vsa_sparsity ${config.VSA_sparsity} \\`) - } - if (config.dit_cpu_offload) lines.push(" --dit_cpu_offload \\") - if (config.dit_layerwise_offload) lines.push(" --dit_layerwise_offload \\") - if (config.vae_cpu_offload) lines.push(" --vae_cpu_offload \\") - if (config.text_encoder_cpu_offload) lines.push(" --text_encoder_cpu_offload \\") - if (config.image_encoder_cpu_offload && (config.workload_type === "i2v" || config.workload_type === "ti2v")) { - lines.push(" --image_encoder_cpu_offload \\") - } - if (config.pin_cpu_memory) lines.push(" --pin_cpu_memory \\") - if (config.use_fsdp_inference && config.num_gpus > 1) lines.push(" --use_fsdp_inference \\") - - if (config.workload_type === "i2v" || config.workload_type === "ti2v") { - lines.push(" --image ./input.png \\") - } - lines.push(' --prompt "your prompt here"') - - return lines.join("\n") - }, [config]) - - const copyCommand = () => { - navigator.clipboard.writeText(command) - setCopied(true) - setTimeout(() => setCopied(false), 2000) - } - - const updateConfig = (key: K, value: Config[K]) => { - setConfig((prev) => ({ ...prev, [key]: value })) - } - - const isFastWanDMD = config.model_id.includes("FastWan") - const isI2V = config.workload_type === "i2v" || config.workload_type === "ti2v" - - return ( -
- {/* Header */} -
-
-
-
- - FastVideo Logo - -
-

Advanced Tuning Guide

-

RTX 4090 / RTX 5090 - All 27 Parameters

-
-
- - Quick Start - -
-
-
- -
- {/* Stats Bar */} -
-
-
-
- - Video Length -
-
{videoLength}s
-
-
-
- - Est. Time -
-
~{estimatedTime}s
-
-
-
- - Total Pixels -
-
{(totalPixels / 1000000).toFixed(1)}M
-
-
-
- - Compute Cost -
-
{(computeCost / 1000000000).toFixed(2)}G
-
-
-
- -
- {/* Left Column - Parameters */} -
- {/* Category A - Model & Hardware */} -
-
-
- updateConfig("model_id", v)} - options={modelOptions.map(m => ({ id: m.id, name: `${m.name} (${m.size})` }))} - tooltip="HuggingFace model path - uniquely identifies the model weights and architecture." - /> -
- updateConfig("workload_type", v)} - options={workloadOptions.map(w => ({ id: w.id, name: w.name }))} - tooltip="Task category. Determines which pipeline stages run." - /> - updateConfig("gpu", v)} - options={gpuOptions.map(g => ({ id: g.id, name: `${g.name} (${g.vram})` }))} - tooltip="GPU model. Used for benchmark tracking and hardware-aware configuration." - /> - updateConfig("num_gpus", v)} - min={1} - max={8} - tooltip="Values > 1 require use_fsdp_inference = true." - /> -
-
- - {/* Category B - Video Spec */} -
-
-
- -
- {resolutionPresets.map((preset) => ( - - ))} -
-
-
- updateConfig("height", v)} - min={256} - max={2160} - step={8} - unit="px" - tooltip="Frame height in pixels. Must be divisible by 8 (VAE requirement)." - /> - updateConfig("width", v)} - min={256} - max={3840} - step={8} - unit="px" - tooltip="Frame width in pixels. Must be divisible by 8." - /> -
-
- -
- {framePresets.map((preset) => ( - - ))} -
-
-
- updateConfig("num_frames", v)} - min={1} - max={240} - tooltip="Total number of frames to generate. Directly sets video duration at a given fps." - /> - updateConfig("fps", v)} - min={1} - max={60} - tooltip="Frames per second for the output video. Does NOT affect generation time." - /> -
-
-
- - {/* Category C - Quality */} -
-
-
- -
- updateConfig("num_inference_steps", Number(e.target.value))} - className="flex-1 h-2 rounded-full bg-slate-700 appearance-none cursor-pointer [&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:h-4 [&::-webkit-slider-thumb]:w-4 [&::-webkit-slider-thumb]:rounded-full [&::-webkit-slider-thumb]:bg-amber-400" - /> - {config.num_inference_steps} -
-
- Draft (10) - Balanced (30) - High (80) -
-
-
- -
- updateConfig("guidance_scale", Number(e.target.value))} - className="flex-1 h-2 rounded-full bg-slate-700 appearance-none cursor-pointer [&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:h-4 [&::-webkit-slider-thumb]:w-4 [&::-webkit-slider-thumb]:rounded-full [&::-webkit-slider-thumb]:bg-amber-400" - /> - {config.guidance_scale} -
-
- Loose (3) - Balanced (5) - Strict (8+) -
-
-
- updateConfig("embedded_cfg_scale", v)} - min={1} - max={10} - step={0.5} - tooltip="Model-level CFG signal passed into the DiT. Default: 6.0. Rarely change." - /> - updateConfig("seed", v)} - min={-1} - tooltip="Random seed. Set to -1 for random. Fix a seed for reproducibility." - /> -
-
-
- - {/* Category D - Speed */} -
-
-
- -
- {attentionBackends.map((backend) => ( - - ))} -
-
- {config.attention_backend === "VIDEO_SPARSE_ATTN" && ( -
- -
- updateConfig("VSA_sparsity", Number(e.target.value))} - className="flex-1 h-2 rounded-full bg-slate-700 appearance-none cursor-pointer [&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:h-4 [&::-webkit-slider-thumb]:w-4 [&::-webkit-slider-thumb]:rounded-full [&::-webkit-slider-thumb]:bg-violet-400" - /> - {config.VSA_sparsity} -
-
- )} - {isFastWanDMD && config.gpu === "rtx4090" && ( -
-
- - DMD Mode Available -
-
- FastWan DMD uses 3-step distillation for ~10x faster generation. -
-
- dmd_steps: {config.dmd_denoising_steps} -
-
- )} -
-
- - {/* Category E - Memory */} -
-
-
-
- Tip: For 24GB VRAM with 14B models, enable dit_cpu_offload + vae_cpu_offload + pin_cpu_memory. -
-
- updateConfig("dit_cpu_offload", v)} - tooltip="Offload entire DiT to RAM. Saves ~4GB, ~2-3x slower." - /> - updateConfig("dit_layerwise_offload", v)} - tooltip="Layer-by-layer offload. Maximum VRAM saving (~8GB), ~4x slower." - /> - updateConfig("vae_cpu_offload", v)} - tooltip="Offload VAE decoder. Saves ~2GB. Minimal time penalty." - /> - updateConfig("text_encoder_cpu_offload", v)} - tooltip="Offload text encoder. Saves ~1-2GB. Runs once at start." - /> - updateConfig("image_encoder_cpu_offload", v)} - tooltip="I2V/TI2V only. Saves ~1-2GB." - disabled={!isI2V} - /> - updateConfig("pin_cpu_memory", v)} - tooltip="Pins RAM pages for faster PCIe DMA transfers. Always enable with any offload flag." - /> - updateConfig("use_fsdp_inference", v)} - tooltip="Shards model weights across multiple GPUs via FSDP." - disabled={config.num_gpus <= 1} - /> -
-
-
- - {/* Right Column - Output */} -
-
- {/* Generated Command */} -
-
-
- - - -

Generated Command

-
- -
-
-
-                    {command}
-                  
-
-
- - {/* Quick Reference */} -
-

Quick Reference

-
-
- Resolution - {config.width}x{config.height} -
-
- Frames - {config.num_frames} -
-
- Steps - {config.num_inference_steps} -
-
- Backend - {config.attention_backend} -
-
- Offloading - - {[config.dit_cpu_offload && "DiT", config.vae_cpu_offload && "VAE"].filter(Boolean).join("+") || "None"} - -
-
-
-
-
-
-
-
- ) -} diff --git a/consumer-guide/components.json b/consumer-guide/components.json deleted file mode 100644 index 4ee62ee10..000000000 --- a/consumer-guide/components.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "$schema": "https://ui.shadcn.com/schema.json", - "style": "new-york", - "rsc": true, - "tsx": true, - "tailwind": { - "config": "", - "css": "app/globals.css", - "baseColor": "neutral", - "cssVariables": true, - "prefix": "" - }, - "aliases": { - "components": "@/components", - "utils": "@/lib/utils", - "ui": "@/components/ui", - "lib": "@/lib", - "hooks": "@/hooks" - }, - "iconLibrary": "lucide" -} diff --git a/consumer-guide/components/theme-provider.tsx b/consumer-guide/components/theme-provider.tsx deleted file mode 100644 index 55c2f6eb6..000000000 --- a/consumer-guide/components/theme-provider.tsx +++ /dev/null @@ -1,11 +0,0 @@ -'use client' - -import * as React from 'react' -import { - ThemeProvider as NextThemesProvider, - type ThemeProviderProps, -} from 'next-themes' - -export function ThemeProvider({ children, ...props }: ThemeProviderProps) { - return {children} -} diff --git a/consumer-guide/components/ui/accordion.tsx b/consumer-guide/components/ui/accordion.tsx deleted file mode 100644 index e538a33b9..000000000 --- a/consumer-guide/components/ui/accordion.tsx +++ /dev/null @@ -1,66 +0,0 @@ -'use client' - -import * as React from 'react' -import * as AccordionPrimitive from '@radix-ui/react-accordion' -import { ChevronDownIcon } from 'lucide-react' - -import { cn } from '@/lib/utils' - -function Accordion({ - ...props -}: React.ComponentProps) { - return -} - -function AccordionItem({ - className, - ...props -}: React.ComponentProps) { - return ( - - ) -} - -function AccordionTrigger({ - className, - children, - ...props -}: React.ComponentProps) { - return ( - - svg]:rotate-180', - className, - )} - {...props} - > - {children} - - - - ) -} - -function AccordionContent({ - className, - children, - ...props -}: React.ComponentProps) { - return ( - -
{children}
-
- ) -} - -export { Accordion, AccordionItem, AccordionTrigger, AccordionContent } diff --git a/consumer-guide/components/ui/alert-dialog.tsx b/consumer-guide/components/ui/alert-dialog.tsx deleted file mode 100644 index 970445266..000000000 --- a/consumer-guide/components/ui/alert-dialog.tsx +++ /dev/null @@ -1,157 +0,0 @@ -'use client' - -import * as React from 'react' -import * as AlertDialogPrimitive from '@radix-ui/react-alert-dialog' - -import { cn } from '@/lib/utils' -import { buttonVariants } from '@/components/ui/button' - -function AlertDialog({ - ...props -}: React.ComponentProps) { - return -} - -function AlertDialogTrigger({ - ...props -}: React.ComponentProps) { - return ( - - ) -} - -function AlertDialogPortal({ - ...props -}: React.ComponentProps) { - return ( - - ) -} - -function AlertDialogOverlay({ - className, - ...props -}: React.ComponentProps) { - return ( - - ) -} - -function AlertDialogContent({ - className, - ...props -}: React.ComponentProps) { - return ( - - - - - ) -} - -function AlertDialogHeader({ - className, - ...props -}: React.ComponentProps<'div'>) { - return ( -
- ) -} - -function AlertDialogFooter({ - className, - ...props -}: React.ComponentProps<'div'>) { - return ( -
- ) -} - -function AlertDialogTitle({ - className, - ...props -}: React.ComponentProps) { - return ( - - ) -} - -function AlertDialogDescription({ - className, - ...props -}: React.ComponentProps) { - return ( - - ) -} - -function AlertDialogAction({ - className, - ...props -}: React.ComponentProps) { - return ( - - ) -} - -function AlertDialogCancel({ - className, - ...props -}: React.ComponentProps) { - return ( - - ) -} - -export { - AlertDialog, - AlertDialogPortal, - AlertDialogOverlay, - AlertDialogTrigger, - AlertDialogContent, - AlertDialogHeader, - AlertDialogFooter, - AlertDialogTitle, - AlertDialogDescription, - AlertDialogAction, - AlertDialogCancel, -} diff --git a/consumer-guide/components/ui/alert.tsx b/consumer-guide/components/ui/alert.tsx deleted file mode 100644 index e6751abe6..000000000 --- a/consumer-guide/components/ui/alert.tsx +++ /dev/null @@ -1,66 +0,0 @@ -import * as React from 'react' -import { cva, type VariantProps } from 'class-variance-authority' - -import { cn } from '@/lib/utils' - -const alertVariants = cva( - 'relative w-full rounded-lg border px-4 py-3 text-sm grid has-[>svg]:grid-cols-[calc(var(--spacing)*4)_1fr] grid-cols-[0_1fr] has-[>svg]:gap-x-3 gap-y-0.5 items-start [&>svg]:size-4 [&>svg]:translate-y-0.5 [&>svg]:text-current', - { - variants: { - variant: { - default: 'bg-card text-card-foreground', - destructive: - 'text-destructive bg-card [&>svg]:text-current *:data-[slot=alert-description]:text-destructive/90', - }, - }, - defaultVariants: { - variant: 'default', - }, - }, -) - -function Alert({ - className, - variant, - ...props -}: React.ComponentProps<'div'> & VariantProps) { - return ( -
- ) -} - -function AlertTitle({ className, ...props }: React.ComponentProps<'div'>) { - return ( -
- ) -} - -function AlertDescription({ - className, - ...props -}: React.ComponentProps<'div'>) { - return ( -
- ) -} - -export { Alert, AlertTitle, AlertDescription } diff --git a/consumer-guide/components/ui/aspect-ratio.tsx b/consumer-guide/components/ui/aspect-ratio.tsx deleted file mode 100644 index 40bb1208d..000000000 --- a/consumer-guide/components/ui/aspect-ratio.tsx +++ /dev/null @@ -1,11 +0,0 @@ -'use client' - -import * as AspectRatioPrimitive from '@radix-ui/react-aspect-ratio' - -function AspectRatio({ - ...props -}: React.ComponentProps) { - return -} - -export { AspectRatio } diff --git a/consumer-guide/components/ui/avatar.tsx b/consumer-guide/components/ui/avatar.tsx deleted file mode 100644 index aa98465a3..000000000 --- a/consumer-guide/components/ui/avatar.tsx +++ /dev/null @@ -1,53 +0,0 @@ -'use client' - -import * as React from 'react' -import * as AvatarPrimitive from '@radix-ui/react-avatar' - -import { cn } from '@/lib/utils' - -function Avatar({ - className, - ...props -}: React.ComponentProps) { - return ( - - ) -} - -function AvatarImage({ - className, - ...props -}: React.ComponentProps) { - return ( - - ) -} - -function AvatarFallback({ - className, - ...props -}: React.ComponentProps) { - return ( - - ) -} - -export { Avatar, AvatarImage, AvatarFallback } diff --git a/consumer-guide/components/ui/badge.tsx b/consumer-guide/components/ui/badge.tsx deleted file mode 100644 index fc4126b7a..000000000 --- a/consumer-guide/components/ui/badge.tsx +++ /dev/null @@ -1,46 +0,0 @@ -import * as React from 'react' -import { Slot } from '@radix-ui/react-slot' -import { cva, type VariantProps } from 'class-variance-authority' - -import { cn } from '@/lib/utils' - -const badgeVariants = cva( - 'inline-flex items-center justify-center rounded-md border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden', - { - variants: { - variant: { - default: - 'border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90', - secondary: - 'border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90', - destructive: - 'border-transparent bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60', - outline: - 'text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground', - }, - }, - defaultVariants: { - variant: 'default', - }, - }, -) - -function Badge({ - className, - variant, - asChild = false, - ...props -}: React.ComponentProps<'span'> & - VariantProps & { asChild?: boolean }) { - const Comp = asChild ? Slot : 'span' - - return ( - - ) -} - -export { Badge, badgeVariants } diff --git a/consumer-guide/components/ui/breadcrumb.tsx b/consumer-guide/components/ui/breadcrumb.tsx deleted file mode 100644 index 1750ff26a..000000000 --- a/consumer-guide/components/ui/breadcrumb.tsx +++ /dev/null @@ -1,109 +0,0 @@ -import * as React from 'react' -import { Slot } from '@radix-ui/react-slot' -import { ChevronRight, MoreHorizontal } from 'lucide-react' - -import { cn } from '@/lib/utils' - -function Breadcrumb({ ...props }: React.ComponentProps<'nav'>) { - return