From 63991d20174b7ff88925e7c9522dbb7b4b4e3965 Mon Sep 17 00:00:00 2001 From: kevin314 Date: Tue, 2 Jun 2026 11:56:04 +0000 Subject: [PATCH] Test --- apps/dreamverse/dreamverse/config.py | 4 +- .../dreamverse/dreamverse/video_generation.py | 5 +- apps/dreamverse/scripts/launch-dreamverse.sh | 9 +- apps/dreamverse/web/src/app/page.tsx | 17 +- .../web/src/components/VideoPlayer.tsx | 4 +- .../web/src/components/Workspace.tsx | 147 ++++++++++-------- 6 files changed, 106 insertions(+), 80 deletions(-) diff --git a/apps/dreamverse/dreamverse/config.py b/apps/dreamverse/dreamverse/config.py index 75ed36bf5..2216f9318 100644 --- a/apps/dreamverse/dreamverse/config.py +++ b/apps/dreamverse/dreamverse/config.py @@ -83,7 +83,7 @@ SESSION_TIMEOUT_SECONDS = 1800 NUM_FRAMES = 121 FRAME_HEIGHT = 1088 FRAME_WIDTH = 1920 -NUM_INFERENCE_STEPS = 5 +NUM_INFERENCE_STEPS = 8 JPEG_QUALITY = 100 BATCH_SIZE = 3 @@ -376,4 +376,4 @@ STARTUP_WARMUP_PROMPT = os.getenv( ("A cinematic drone shot over coastal cliffs at sunrise, " "golden light, gentle ocean waves, ultra detailed"), ).strip() -STARTUP_WARMUP_TIMEOUT_SECONDS = max(1, _env_int("FASTVIDEO_STARTUP_WARMUP_TIMEOUT_SECONDS", 2400)) +STARTUP_WARMUP_TIMEOUT_SECONDS = max(1, _env_int("FASTVIDEO_STARTUP_WARMUP_TIMEOUT_SECONDS", 24000)) diff --git a/apps/dreamverse/dreamverse/video_generation.py b/apps/dreamverse/dreamverse/video_generation.py index 88dd49343..1f5d5ef28 100644 --- a/apps/dreamverse/dreamverse/video_generation.py +++ b/apps/dreamverse/dreamverse/video_generation.py @@ -265,6 +265,7 @@ class VideoGenerationWorker: EngineConfig, GeneratorConfig, OffloadConfig, + ParallelismConfig, PipelineSelection, QuantizationConfig, ) @@ -316,7 +317,7 @@ class VideoGenerationWorker: preset_overrides={ "refine": { "enabled": True, - "num_inference_steps": 2, + "num_inference_steps": 3, "guidance_scale": 1.0, "add_noise": True, }, @@ -489,7 +490,7 @@ class VideoGenerationWorker: num_inference_steps=NUM_INFERENCE_STEPS, guidance_scale=1.0, seed=10, - ltx2_image_crf=0.0, + ltx2_image_crf=(33.0 if image_path and segment_idx == 1 else 0.0), image_path=image_path if segment_idx == 1 else None, return_continuation_state=False, ) diff --git a/apps/dreamverse/scripts/launch-dreamverse.sh b/apps/dreamverse/scripts/launch-dreamverse.sh index e32b48bd1..ca7ac455d 100755 --- a/apps/dreamverse/scripts/launch-dreamverse.sh +++ b/apps/dreamverse/scripts/launch-dreamverse.sh @@ -13,11 +13,12 @@ GXX="$CONDA_PREFIX/bin/aarch64-conda-linux-gnu-g++" export CUDA_HOME="$CONDA_PREFIX" export FASTVIDEO_ENABLE_STARTUP_WARMUP=true -export DREAMVERSE_MAX_AUTOTUNE=false +export FASTVIDEO_ENABLE_PROMPT_SAFETY=true +export DREAMVERSE_MAX_AUTOTUNE=true export LTX2_USE_DISTILLED_SIGMAS=0 export DREAMVERSE_SESSION_TIMEOUT_SECONDS=1800 export CEREBRAS_API_KEY="${CEREBRAS_API_KEY:-}" # set this in your env or ~/.env -export FASTVIDEO_PROMPT_CEREBRAS_MODEL="ifm-k2-think-v2" +export FASTVIDEO_PROMPT_CEREBRAS_MODEL="gpt-oss-120b" export TORCHINDUCTOR_CACHE_DIR="$HOME/.cache/torchinductor" export TRITON_CACHE_DIR="$HOME/.triton/cache" export TORCH_CUDA_ARCH_LIST="10.0a" @@ -35,7 +36,9 @@ export LIBRARY_PATH="$CONDA_PREFIX/lib/cuda-compat:$CONDA_PREFIX/lib/stubs" # Only libcudart.so.12 at runtime — prevents cuDNN from seeing .so.13 export LD_LIBRARY_PATH="$CUDA_RT_DIR" -CUDA_VISIBLE_DEVICES="${CUDA_VISIBLE_DEVICES:-0}" +CUDA_VISIBLE_DEVICES="${CUDA_VISIBLE_DEVICES:-0,1,2,3}" +export FASTVIDEO_GPU_COUNT="${FASTVIDEO_GPU_COUNT:-all}" +export DREAMVERSE_SP_SIZE="${DREAMVERSE_SP_SIZE:-4}" PORT="${DREAMVERSE_PORT:-8009}" FFMPEG_ENV="$(dirname "$0")/ffmpeg-env.sh" diff --git a/apps/dreamverse/web/src/app/page.tsx b/apps/dreamverse/web/src/app/page.tsx index ec9ac7177..234857284 100644 --- a/apps/dreamverse/web/src/app/page.tsx +++ b/apps/dreamverse/web/src/app/page.tsx @@ -9,7 +9,7 @@ import SessionTimeoutModal from "@/components/SessionTimeoutModal"; import Sidebar from "@/components/Sidebar"; import Header from "@/components/Header"; import VideoPlayer from "@/components/VideoPlayer"; -import Workspace from "@/components/Workspace"; +import Workspace, { SceneHistoryList } from "@/components/Workspace"; import { saveProject, saveProjectMetadata, listProjects, loadProjectClips, deleteProject, pruneOldProjects, type StoredProject, type StoredClip } from "@/lib/projectStorage"; import { isInfrastructureError } from "@/lib/ws/reducer"; import { useStore } from "@/hooks/useStore"; @@ -80,7 +80,7 @@ function yieldToEventLoop(): Promise { const HERO_WAVE_LIGHT = ["#2A4A98", "#4878E5", "#6FA0F2", "#B0BCC8", "#E8D99E", "#D8C844", "#C2A620"]; const HERO_WAVE_DARK = ["#143468", "#1E58B8", "#3892F0", "#80B8E8", "#B8D0EA", "#E2D498", "#DABB50"]; -const HERO_TEXT = "Direct scenes in seconds"; +const HERO_TEXT = "Direct scenes in seconds with"; function HeroTagline() { const ref = useRef(null); @@ -166,6 +166,8 @@ function HeroTagline() { ))} + {" "} + FastVideo ); } @@ -467,9 +469,8 @@ export default function Page() { const hasEdits = useMemo( () => Boolean(sessionStarted) && ( (promptEvents as Record[]).some((e) => typeof e?.text === "string" && e.text.trim() && String(e?.source || "").trim() === "user_rewrite") - || (Boolean(manualContinuationMode) && steeringScenes.length > 0) ), - [sessionStarted, promptEvents, manualContinuationMode, steeringScenes], + [sessionStarted, promptEvents], ); // Viewing mode: track which clip is selected (defaults to last clip) @@ -2711,6 +2712,7 @@ export default function Page() { />
setSidebarOpen((prev) => !prev)} /> +
{isViewingMode && ( <> @@ -2806,7 +2808,6 @@ export default function Page() { )?.label || ""} sessionStarted={sessionStarted as boolean} @@ -2877,6 +2878,12 @@ export default function Page() {
+ {manualContinuationMode && ( +
+ +
+ )} + ); } diff --git a/apps/dreamverse/web/src/components/VideoPlayer.tsx b/apps/dreamverse/web/src/components/VideoPlayer.tsx index a148f211c..36ab9f5db 100644 --- a/apps/dreamverse/web/src/components/VideoPlayer.tsx +++ b/apps/dreamverse/web/src/components/VideoPlayer.tsx @@ -174,8 +174,8 @@ export default function VideoPlayer({ }; }, [generatingNext, sessionStarted]); - // Drive a ~4.5s progress bar during generation so the wait has a visible ETA. - const GEN_DURATION_MS = 4500; + // Drive a 12s progress bar during generation so the wait has a visible ETA. + const GEN_DURATION_MS = 12000; const [genProgress, setGenProgress] = useState(0); useEffect(() => { if (!generatingNext) { diff --git a/apps/dreamverse/web/src/components/Workspace.tsx b/apps/dreamverse/web/src/components/Workspace.tsx index 5b771b305..7411234f0 100644 --- a/apps/dreamverse/web/src/components/Workspace.tsx +++ b/apps/dreamverse/web/src/components/Workspace.tsx @@ -8,6 +8,85 @@ import { Check, Clapperboard, Lightbulb, Pencil } from "lucide-react"; export const WORKSPACE_ORIGINAL_SELECTION_KEY = "original"; export const WORKSPACE_CURRENT_SELECTION_KEY = "current"; +export function SceneHistoryList({ sceneHistory = [] }: { sceneHistory?: Record[] }) { + const bottomSentinelRef = useRef(null); + const topSentinelRef = useRef(null); + const [showTopFade, setShowTopFade] = useState(false); + + const scenes = useMemo( + () => (sceneHistory || []).filter((s) => normalizeText(s?.prompt)), + [sceneHistory], + ); + + const scrollToBottom = useCallback(() => { + setTimeout(() => { + bottomSentinelRef.current?.scrollIntoView({ block: "end", behavior: "smooth" }); + }, 60); + }, []); + + useEffect(() => { + if (scenes.length > 0) scrollToBottom(); + }, [scenes.length, scrollToBottom]); + + useEffect(() => { + const sentinel = bottomSentinelRef.current; + if (!sentinel || typeof ResizeObserver === "undefined") return; + let container: HTMLElement | null = sentinel.parentElement; + while (container) { + const oy = getComputedStyle(container).overflowY; + if (oy === "auto" || oy === "scroll") break; + container = container.parentElement; + } + if (!container) return; + const ro = new ResizeObserver(() => { + const nearBottom = container!.scrollHeight - container!.scrollTop - container!.clientHeight < 96; + if (nearBottom) scrollToBottom(); + }); + ro.observe(container); + return () => ro.disconnect(); + }, [scenes.length, scrollToBottom]); + + useEffect(() => { + const el = topSentinelRef.current; + if (!el) return; + const observer = new IntersectionObserver(([entry]) => setShowTopFade(!entry.isIntersecting), { threshold: 0.1 }); + observer.observe(el); + return () => observer.disconnect(); + }, [scenes.length]); + + if (scenes.length === 0) return null; + + return ( +
+
+ ); +} + interface WorkspaceProps { promptEvents?: Record[]; currentThumbnail?: string | null; @@ -20,7 +99,6 @@ interface WorkspaceProps { selectedEntryKey?: string; originalClipId?: string; manualMode?: boolean; - sceneHistory?: Record[]; } function normalizeText(value: any): string { @@ -220,7 +298,7 @@ function ChromaGradient({ sessionStarted = false }: { sessionStarted?: boolean } ); } -export default function Workspace({ promptEvents = [], currentThumbnail = null, originalLabel = "", sessionStarted = false, onSelectOriginal, onSelectEvent, onSelectCurrent, selectedClipId, selectedEntryKey: selectedEntryKeyProp, originalClipId = "", manualMode = false, sceneHistory = [] }: WorkspaceProps) { +export default function Workspace({ promptEvents = [], currentThumbnail = null, originalLabel = "", sessionStarted = false, onSelectOriginal, onSelectEvent, onSelectCurrent, selectedClipId, selectedEntryKey: selectedEntryKeyProp, originalClipId = "", manualMode = false }: WorkspaceProps) { const bottomSentinelRef = useRef(null); const topSentinelRef = useRef(null); const [showTopFade, setShowTopFade] = useState(false); @@ -243,13 +321,6 @@ export default function Workspace({ promptEvents = [], currentThumbnail = null, return WORKSPACE_CURRENT_SELECTION_KEY; }, [selectedEntryKeyProp, selectedClipId, originalClipId, conversationEvents]); - // Steering mode: an elegant per-segment list of each scene's prompt (oldest first, - // already resolved upstream to prefer the user's own prompt). - const scenes = useMemo( - () => (sceneHistory || []).filter((s) => normalizeText(s?.prompt)), - [sceneHistory], - ); - const scrollToBottom = useCallback(() => { setTimeout(() => { bottomSentinelRef.current?.scrollIntoView({ block: "end", behavior: "smooth" }); @@ -260,74 +331,18 @@ export default function Workspace({ promptEvents = [], currentThumbnail = null, if (conversationEvents.length > 0) scrollToBottom(); }, [conversationEvents, scrollToBottom]); - useEffect(() => { - if (manualMode && scenes.length > 0) scrollToBottom(); - }, [manualMode, scenes.length, scrollToBottom]); - - // The scene list lives in a flex-1 area that shrinks when the ChatBar grows (e.g. the - // "Segment complete" banner appears). Without re-scrolling, the latest scene gets clipped - // behind the ChatBar. Re-pin to the bottom whenever the scroll container resizes — unless - // the user has scrolled up to read earlier scenes. - useEffect(() => { - if (!manualMode) return; - const sentinel = bottomSentinelRef.current; - if (!sentinel || typeof ResizeObserver === "undefined") return; - let container: HTMLElement | null = sentinel.parentElement; - while (container) { - const oy = getComputedStyle(container).overflowY; - if (oy === "auto" || oy === "scroll") break; - container = container.parentElement; - } - if (!container) return; - const ro = new ResizeObserver(() => { - const nearBottom = container!.scrollHeight - container!.scrollTop - container!.clientHeight < 96; - if (nearBottom) scrollToBottom(); - }); - ro.observe(container); - return () => ro.disconnect(); - }, [manualMode, scenes.length, scrollToBottom]); - useEffect(() => { const el = topSentinelRef.current; if (!el) return; const observer = new IntersectionObserver(([entry]) => setShowTopFade(!entry.isIntersecting), { threshold: 0.1 }); observer.observe(el); return () => observer.disconnect(); - }, [conversationEvents.length, manualMode, scenes.length]); + }, [conversationEvents.length]); if (manualMode) { return (
- {scenes.length >= 1 && ( -
-
- )}
); }