Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions frontend/src/components/DownloadDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@ import {
DialogTitle,
} from "./ui/dialog";
import { Progress } from "./ui/progress";
import { PIPELINES } from "../data/pipelines";
import type { PipelineId, DownloadProgress } from "../types";
import type { PipelineInfo } from "../hooks/usePipelines";

interface DownloadDialogProps {
open: boolean;
pipelines: Record<string, PipelineInfo> | null;
pipelineId: PipelineId;
onClose: () => void;
onDownload: () => void;
Expand All @@ -23,13 +24,14 @@ interface DownloadDialogProps {

export function DownloadDialog({
open,
pipelines,
pipelineId,
onClose,
onDownload,
isDownloading = false,
progress = null,
}: DownloadDialogProps) {
const pipelineInfo = PIPELINES[pipelineId];
const pipelineInfo = pipelines?.[pipelineId];
if (!pipelineInfo) return null;

return (
Expand Down
13 changes: 10 additions & 3 deletions frontend/src/components/InputAndControlsPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { LabelWithTooltip } from "./ui/label-with-tooltip";
import type { VideoSourceMode } from "../hooks/useVideoSource";
import type { PromptItem, PromptTransition } from "../lib/api";
import type { InputMode } from "../types";
import { pipelineIsMultiMode } from "../data/pipelines";
import type { PipelineInfo } from "../hooks/usePipelines";
import { PromptInput } from "./PromptInput";
import { TimelinePromptEditor } from "./TimelinePromptEditor";
import type { TimelinePrompt } from "./PromptTimeline";
Expand All @@ -24,6 +24,7 @@ import { Button } from "./ui/button";

interface InputAndControlsPanelProps {
className?: string;
pipelines: Record<string, PipelineInfo> | null;
localStream: MediaStream | null;
isInitializing: boolean;
error: string | null;
Expand Down Expand Up @@ -73,6 +74,7 @@ interface InputAndControlsPanelProps {

export function InputAndControlsPanel({
className = "",
pipelines,
localStream,
isInitializing,
error,
Expand Down Expand Up @@ -128,7 +130,8 @@ export function InputAndControlsPanel({
const videoRef = useRef<HTMLVideoElement>(null);

// Check if this pipeline supports multiple input modes
const isMultiMode = pipelineIsMultiMode(pipelineId);
const pipeline = pipelines?.[pipelineId];
const isMultiMode = (pipeline?.supportedModes?.length ?? 0) > 1;

useEffect(() => {
if (videoRef.current && localStream) {
Expand Down Expand Up @@ -329,6 +332,11 @@ export function InputAndControlsPanel({
// The Input can have two states: Append (default) and Edit (when a prompt is selected and the video is paused)
const isEditMode = selectedTimelinePrompt && isVideoPaused;

// Hide prompts section if pipeline doesn't support prompts
if (pipeline?.supportsPrompts === false) {
return null;
}

return (
<div>
<div className="flex items-center justify-between mb-2">
Expand Down Expand Up @@ -358,7 +366,6 @@ export function InputAndControlsPanel({
onPromptsSubmit={onPromptsSubmit}
onTransitionSubmit={onTransitionSubmit}
disabled={
pipelineId === "passthrough" ||
(_isTimelinePlaying &&
!isVideoPaused &&
!isAtEndOfTimeline()) ||
Expand Down
53 changes: 15 additions & 38 deletions frontend/src/components/SettingsPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,7 @@ import { Input } from "./ui/input";
import { Button } from "./ui/button";
import { Toggle } from "./ui/toggle";
import { SliderWithInput } from "./ui/slider-with-input";
import { Hammer, Info, Minus, Plus, RotateCcw } from "lucide-react";
import {
PIPELINES,
pipelineSupportsLoRA,
pipelineSupportsVACE,
} from "../data/pipelines";
import { Info, Minus, Plus, RotateCcw } from "lucide-react";
import { PARAMETER_METADATA } from "../data/parameterMetadata";
import { DenoisingStepsSlider } from "./DenoisingStepsSlider";
import { useLocalSliderValue } from "../hooks/useLocalSliderValue";
Expand All @@ -35,12 +30,14 @@ import type {
SettingsState,
InputMode,
} from "../types";
import type { PipelineInfo } from "../hooks/usePipelines";
import { LoRAManager } from "./LoRAManager";

const MIN_DIMENSION = 16;

interface SettingsPanelProps {
className?: string;
pipelines: Record<string, PipelineInfo> | null;
pipelineId: PipelineId;
onPipelineIdChange?: (pipelineId: PipelineId) => void;
isStreaming?: boolean;
Expand Down Expand Up @@ -89,6 +86,7 @@ interface SettingsPanelProps {

export function SettingsPanel({
className = "",
pipelines,
pipelineId,
onPipelineIdChange,
isStreaming = false,
Expand Down Expand Up @@ -141,7 +139,7 @@ export function SettingsPanel({
const [seedError, setSeedError] = useState<string | null>(null);

const handlePipelineIdChange = (value: string) => {
if (value in PIPELINES) {
if (pipelines && value in pipelines) {
onPipelineIdChange?.(value as PipelineId);
}
};
Expand Down Expand Up @@ -235,7 +233,7 @@ export function SettingsPanel({
handleSeedChange(newValue);
};

const currentPipeline = PIPELINES[pipelineId];
const currentPipeline = pipelines?.[pipelineId];

return (
<Card className={`h-full flex flex-col ${className}`}>
Expand All @@ -254,11 +252,12 @@ export function SettingsPanel({
<SelectValue placeholder="Select a pipeline" />
</SelectTrigger>
<SelectContent>
{Object.keys(PIPELINES).map(id => (
<SelectItem key={id} value={id}>
{id}
</SelectItem>
))}
{pipelines &&
Object.keys(pipelines).map(id => (
<SelectItem key={id} value={id}>
{id}
</SelectItem>
))}
</SelectContent>
</Select>
</div>
Expand All @@ -273,9 +272,7 @@ export function SettingsPanel({
</div>

<div>
{(currentPipeline.about ||
currentPipeline.docsUrl ||
currentPipeline.modified) && (
{(currentPipeline.about || currentPipeline.docsUrl) && (
<div className="flex items-stretch gap-1 h-6">
{currentPipeline.about && (
<TooltipProvider>
Expand All @@ -294,26 +291,6 @@ export function SettingsPanel({
</Tooltip>
</TooltipProvider>
)}
{currentPipeline.modified && (
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think the modified attribute was adding any value so opted to just remove to simplify since we were moving a bunch of attributes to the backend.

<TooltipProvider>
<Tooltip>
<TooltipTrigger asChild>
<Badge
variant="outline"
className="cursor-help hover:bg-accent h-full flex items-center justify-center"
>
<Hammer className="h-3.5 w-3.5" />
</Badge>
</TooltipTrigger>
<TooltipContent>
<p>
This pipeline contains modifications based on the
original project.
</p>
</TooltipContent>
</Tooltip>
</TooltipProvider>
)}
{currentPipeline.docsUrl && (
<a
href={currentPipeline.docsUrl}
Expand All @@ -337,7 +314,7 @@ export function SettingsPanel({
)}

{/* VACE Toggle */}
{pipelineSupportsVACE(pipelineId) && (
{currentPipeline?.supportsVACE && (
<div className="space-y-2">
<div className="flex items-center justify-between gap-2">
<LabelWithTooltip
Expand Down Expand Up @@ -384,7 +361,7 @@ export function SettingsPanel({
</div>
)}

{pipelineSupportsLoRA(pipelineId) && (
{currentPipeline?.supportsLoRA && (
<div className="space-y-4">
<LoRAManager
loras={loras}
Expand Down
123 changes: 1 addition & 122 deletions frontend/src/data/pipelines.ts
Original file line number Diff line number Diff line change
@@ -1,133 +1,12 @@
import type { InputMode } from "../types";

// Unified default prompts by mode (not per-pipeline)
// These are used across all pipelines for consistency
// Default prompts by mode - used across all pipelines for consistency
export const DEFAULT_PROMPTS: Record<InputMode, string> = {
text: "A 3D animated scene. A **panda** walks along a path towards the camera in a park on a spring day.",
video:
"A 3D animated scene. A **panda** sitting in the grass, looking around.",
};

export interface PipelineInfo {
name: string;
about: string;
docsUrl?: string;
modified?: boolean;
estimatedVram?: number; // GB
requiresModels?: boolean; // Whether this pipeline requires models to be downloaded
defaultTemporalInterpolationMethod?: "linear" | "slerp"; // Default method for temporal interpolation
defaultTemporalInterpolationSteps?: number; // Default number of steps for temporal interpolation
supportsLoRA?: boolean; // Whether this pipeline supports LoRA adapters
supportsVACE?: boolean; // Whether this pipeline supports VACE (Video All-In-One Creation and Editing)

// Multi-mode support
supportedModes: InputMode[];
defaultMode: InputMode;
}

export const PIPELINES: Record<string, PipelineInfo> = {
streamdiffusionv2: {
name: "StreamDiffusionV2",
docsUrl:
"https://github.com/daydreamlive/scope/blob/main/src/scope/core/pipelines/streamdiffusionv2/docs/usage.md",
about:
"A streaming pipeline and autoregressive video diffusion model from the creators of the original StreamDiffusion project. The model is trained using Self-Forcing on Wan2.1 1.3b with modifications to support streaming. Includes VACE (All-In-One Video Creation and Editing) for reference image conditioning and structural guidance (depth, flow, pose).",
modified: true,
estimatedVram: 20,
requiresModels: true,
defaultTemporalInterpolationMethod: "slerp",
defaultTemporalInterpolationSteps: 0,
supportsLoRA: true,
supportsVACE: true,
// Multi-mode support
supportedModes: ["text", "video"],
defaultMode: "video",
},
longlive: {
name: "LongLive",
docsUrl:
"https://github.com/daydreamlive/scope/blob/main/src/scope/core/pipelines/longlive/docs/usage.md",
about:
"A streaming pipeline and autoregressive video diffusion model from Nvidia, MIT, HKUST, HKU and THU. The model is trained using Self-Forcing on Wan2.1 1.3b with modifications to support smoother prompt switching and improved quality over longer time periods while maintaining fast generation. Includes VACE (All-In-One Video Creation and Editing) for reference image conditioning and structural guidance (depth, flow, pose).",
modified: true,
estimatedVram: 20,
requiresModels: true,
defaultTemporalInterpolationMethod: "slerp",
defaultTemporalInterpolationSteps: 0,
supportsLoRA: true,
supportsVACE: true,
// Multi-mode support
supportedModes: ["text", "video"],
defaultMode: "text",
},
"krea-realtime-video": {
name: "Krea Realtime Video",
docsUrl:
"https://github.com/daydreamlive/scope/blob/main/src/scope/core/pipelines/krea_realtime_video/docs/usage.md",
about:
"A streaming pipeline and autoregressive video diffusion model from Krea. The model is trained using Self-Forcing on Wan2.1 14b.",
modified: true,
estimatedVram: 32,
requiresModels: true,
defaultTemporalInterpolationMethod: "linear",
defaultTemporalInterpolationSteps: 4,
supportsLoRA: true,
// Multi-mode support
supportedModes: ["text", "video"],
defaultMode: "text",
},
"reward-forcing": {
name: "RewardForcing",
docsUrl:
"https://github.com/daydreamlive/scope/blob/main/src/scope/core/pipelines/reward_forcing/docs/usage.md",
about:
"A streaming pipeline and autoregressive video diffusion model from ZJU, Ant Group, SIAS-ZJU, HUST and SJTU. The model is trained with Rewarded Distribution Matching Distillation using Wan2.1 1.3b as the base model. Includes VACE (All-In-One Video Creation and Editing) for reference image conditioning and structural guidance (depth, flow, pose).",
modified: true,
estimatedVram: 20,
requiresModels: true,
defaultTemporalInterpolationMethod: "slerp",
defaultTemporalInterpolationSteps: 0,
supportsLoRA: true,
supportsVACE: true,
// Multi-mode support
supportedModes: ["text", "video"],
defaultMode: "text",
},
passthrough: {
name: "Passthrough",
about:
"A pipeline that returns the input video without any processing that is useful for testing and debugging.",
requiresModels: false,
// Video-only pipeline
supportedModes: ["video"],
defaultMode: "video",
},
};

export function pipelineSupportsLoRA(pipelineId: string): boolean {
return PIPELINES[pipelineId]?.supportsLoRA === true;
}

export function pipelineSupportsVACE(pipelineId: string): boolean {
return PIPELINES[pipelineId]?.supportsVACE === true;
}

export function pipelineSupportsMode(
pipelineId: string,
mode: InputMode
): boolean {
return PIPELINES[pipelineId]?.supportedModes?.includes(mode) ?? false;
}

export function pipelineIsMultiMode(pipelineId: string): boolean {
const modes = PIPELINES[pipelineId]?.supportedModes ?? [];
return modes.length > 1;
}

export function getPipelineDefaultMode(pipelineId: string): InputMode {
return PIPELINES[pipelineId]?.defaultMode ?? "text";
}

export function getDefaultPromptForMode(mode: InputMode): string {
return DEFAULT_PROMPTS[mode];
}
Loading
Loading