Skip to content

Commit 90846c1

Browse files
committed
Fixes
Disconnect cloud stream on timeline reset Keep resolution to multiples of 64 for cloud
1 parent a136d6f commit 90846c1

File tree

6 files changed

+139
-88
lines changed

6 files changed

+139
-88
lines changed

frontend/src/components/InputAndControlsPanel.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ interface InputAndControlsPanelProps {
4949
timelinePrompts?: TimelinePrompt[];
5050
transitionSteps: number;
5151
onTransitionStepsChange: (steps: number) => void;
52+
cloudMode?: boolean;
5253
}
5354

5455
export function InputAndControlsPanel({
@@ -84,6 +85,7 @@ export function InputAndControlsPanel({
8485
timelinePrompts: _timelinePrompts = [],
8586
transitionSteps,
8687
onTransitionStepsChange,
88+
cloudMode = false,
8789
}: InputAndControlsPanelProps) {
8890
// Helper function to determine if playhead is at the end of timeline
8991
const isAtEndOfTimeline = () => {
@@ -271,6 +273,7 @@ export function InputAndControlsPanel({
271273
transitionSteps={transitionSteps}
272274
onTransitionStepsChange={onTransitionStepsChange}
273275
timelinePrompts={_timelinePrompts}
276+
cloudMode={cloudMode}
274277
/>
275278
)}
276279
</div>

frontend/src/components/PromptInput.tsx

Lines changed: 69 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ interface PromptInputProps {
3232
transitionSteps?: number;
3333
onTransitionStepsChange?: (steps: number) => void;
3434
timelinePrompts?: TimelinePrompt[];
35+
cloudMode?: boolean;
3536
}
3637

3738
export function PromptInput({
@@ -51,6 +52,7 @@ export function PromptInput({
5152
transitionSteps = 4,
5253
onTransitionStepsChange,
5354
timelinePrompts = [],
55+
cloudMode = false,
5456
}: PromptInputProps) {
5557
const [isProcessing, setIsProcessing] = useState(false);
5658
const [focusedIndex, setFocusedIndex] = useState<number | null>(null);
@@ -160,7 +162,8 @@ export function PromptInput({
160162
/>
161163
</div>
162164

163-
<div className="space-y-2">
165+
<div className="space-y-2">
166+
{!cloudMode && (
164167
<TemporalTransitionControls
165168
transitionSteps={transitionSteps}
166169
onTransitionStepsChange={steps => onTransitionStepsChange?.(steps)}
@@ -171,42 +174,43 @@ export function PromptInput({
171174
disabled={disabled || !isStreaming || timelinePrompts.length === 0}
172175
className="space-y-2"
173176
/>
177+
)}
174178

175-
{/* Add/Submit buttons - Bottom row */}
176-
<div className="flex items-center justify-end gap-2">
177-
{managedPrompts.length < 4 && (
178-
<Button
179-
onMouseDown={e => {
180-
e.preventDefault();
181-
handleAddPrompt();
182-
}}
183-
disabled={disabled}
184-
size="sm"
185-
variant="ghost"
186-
className="rounded-full w-8 h-8 p-0"
187-
>
188-
<Plus className="h-4 w-4" />
189-
</Button>
190-
)}
179+
{/* Add/Submit buttons - Bottom row */}
180+
<div className="flex items-center justify-end gap-2">
181+
{managedPrompts.length < 4 && (
191182
<Button
192183
onMouseDown={e => {
193184
e.preventDefault();
194-
handleSubmit();
185+
handleAddPrompt();
195186
}}
196-
disabled={
197-
disabled ||
198-
!managedPrompts.some(p => p.text.trim()) ||
199-
isProcessing
200-
}
187+
disabled={disabled}
201188
size="sm"
202-
className="rounded-full w-8 h-8 p-0 bg-black hover:bg-gray-800 text-white disabled:opacity-50 disabled:cursor-not-allowed"
189+
variant="ghost"
190+
className="rounded-full w-8 h-8 p-0"
203191
>
204-
{isProcessing ? "..." : <ArrowUp className="h-4 w-4" />}
192+
<Plus className="h-4 w-4" />
205193
</Button>
206-
</div>
194+
)}
195+
<Button
196+
onMouseDown={e => {
197+
e.preventDefault();
198+
handleSubmit();
199+
}}
200+
disabled={
201+
disabled ||
202+
!managedPrompts.some(p => p.text.trim()) ||
203+
isProcessing
204+
}
205+
size="sm"
206+
className="rounded-full w-8 h-8 p-0 bg-black hover:bg-gray-800 text-white disabled:opacity-50 disabled:cursor-not-allowed"
207+
>
208+
{isProcessing ? "..." : <ArrowUp className="h-4 w-4" />}
209+
</Button>
207210
</div>
208211
</div>
209-
);
212+
</div>
213+
);
210214
}
211215

212216
// Multiple prompts mode: show weights and controls
@@ -241,43 +245,47 @@ export function PromptInput({
241245
})}
242246

243247
<div className="space-y-2">
244-
{/* Spatial Blend - only for multiple prompts */}
245-
{managedPrompts.length >= 2 && (
246-
<div className="flex items-center justify-between gap-2">
247-
<span className="text-xs text-muted-foreground">
248-
Spatial Blend:
249-
</span>
250-
<Select
251-
value={interpolationMethod}
252-
onValueChange={value =>
253-
onInterpolationMethodChange?.(value as "linear" | "slerp")
248+
{!cloudMode && (
249+
<>
250+
{/* Spatial Blend - only for multiple prompts */}
251+
{managedPrompts.length >= 2 && (
252+
<div className="flex items-center justify-between gap-2">
253+
<span className="text-xs text-muted-foreground">
254+
Spatial Blend:
255+
</span>
256+
<Select
257+
value={interpolationMethod}
258+
onValueChange={value =>
259+
onInterpolationMethodChange?.(value as "linear" | "slerp")
260+
}
261+
disabled={disabled}
262+
>
263+
<SelectTrigger className="w-24 h-6 text-xs">
264+
<SelectValue />
265+
</SelectTrigger>
266+
<SelectContent>
267+
<SelectItem value="linear">Linear</SelectItem>
268+
<SelectItem value="slerp" disabled={managedPrompts.length > 2}>
269+
Slerp
270+
</SelectItem>
271+
</SelectContent>
272+
</Select>
273+
</div>
274+
)}
275+
276+
<TemporalTransitionControls
277+
transitionSteps={transitionSteps}
278+
onTransitionStepsChange={steps => onTransitionStepsChange?.(steps)}
279+
temporalInterpolationMethod={temporalInterpolationMethod}
280+
onTemporalInterpolationMethodChange={method =>
281+
onTemporalInterpolationMethodChange?.(method)
254282
}
255-
disabled={disabled}
256-
>
257-
<SelectTrigger className="w-24 h-6 text-xs">
258-
<SelectValue />
259-
</SelectTrigger>
260-
<SelectContent>
261-
<SelectItem value="linear">Linear</SelectItem>
262-
<SelectItem value="slerp" disabled={managedPrompts.length > 2}>
263-
Slerp
264-
</SelectItem>
265-
</SelectContent>
266-
</Select>
267-
</div>
283+
disabled={disabled || !isStreaming || timelinePrompts.length === 0}
284+
className="space-y-2"
285+
/>
286+
</>
268287
)}
269288

270-
<TemporalTransitionControls
271-
transitionSteps={transitionSteps}
272-
onTransitionStepsChange={steps => onTransitionStepsChange?.(steps)}
273-
temporalInterpolationMethod={temporalInterpolationMethod}
274-
onTemporalInterpolationMethodChange={method =>
275-
onTemporalInterpolationMethodChange?.(method)
276-
}
277-
disabled={disabled || !isStreaming || timelinePrompts.length === 0}
278-
className="space-y-2"
279-
/>
280-
281289
{/* Add/Submit buttons - Bottom row */}
282290
<div className="flex items-center justify-end gap-2">
283291
{managedPrompts.length < 4 && (

frontend/src/components/SettingsPanel.tsx

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,13 @@ export function SettingsPanel({
161161
} else {
162162
setWidthError(`Must be at most ${maxValue}`);
163163
}
164+
} else if (cloudMode && value % 64 !== 0) {
165+
// In cloud mode, dimension must be a multiple of 64
166+
if (dimension === "height") {
167+
setHeightError(`Must be a multiple of 64 in cloud mode`);
168+
} else {
169+
setWidthError(`Must be a multiple of 64 in cloud mode`);
170+
}
164171
} else {
165172
// Clear error if valid
166173
if (dimension === "height") {
@@ -179,7 +186,18 @@ export function SettingsPanel({
179186

180187
const incrementResolution = (dimension: "height" | "width") => {
181188
const maxValue = 2048;
182-
const newValue = Math.min(maxValue, effectiveResolution[dimension] + 1);
189+
const currentValue = effectiveResolution[dimension];
190+
191+
let newValue: number;
192+
if (cloudMode && currentValue % 64 !== 0) {
193+
// Snap to next multiple of 64
194+
newValue = Math.ceil(currentValue / 64) * 64;
195+
} else {
196+
const step = cloudMode ? 64 : 1;
197+
newValue = currentValue + step;
198+
}
199+
200+
newValue = Math.min(maxValue, newValue);
183201
handleResolutionChange(dimension, newValue);
184202
};
185203

@@ -190,7 +208,18 @@ export function SettingsPanel({
190208
pipelineId === "krea-realtime-video"
191209
? MIN_DIMENSION
192210
: 1;
193-
const newValue = Math.max(minValue, effectiveResolution[dimension] - 1);
211+
const currentValue = effectiveResolution[dimension];
212+
213+
let newValue: number;
214+
if (cloudMode && currentValue % 64 !== 0) {
215+
// Snap to previous multiple of 64
216+
newValue = Math.floor(currentValue / 64) * 64;
217+
} else {
218+
const step = cloudMode ? 64 : 1;
219+
newValue = currentValue - step;
220+
}
221+
222+
newValue = Math.max(minValue, newValue);
194223
handleResolutionChange(dimension, newValue);
195224
};
196225

@@ -453,6 +482,7 @@ export function SettingsPanel({
453482
className="text-center border-0 focus-visible:ring-0 focus-visible:ring-offset-0 h-8 [appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none"
454483
min={MIN_DIMENSION}
455484
max={2048}
485+
step={cloudMode ? 64 : 1}
456486
/>
457487
<Button
458488
variant="ghost"
@@ -502,6 +532,7 @@ export function SettingsPanel({
502532
className="text-center border-0 focus-visible:ring-0 focus-visible:ring-offset-0 h-8 [appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none"
503533
min={MIN_DIMENSION}
504534
max={2048}
535+
step={cloudMode ? 64 : 1}
505536
/>
506537
<Button
507538
variant="ghost"

frontend/src/data/pipelines.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,8 @@ export const PIPELINES: Record<string, PipelineInfo> = {
6565
defaultTemporalInterpolationSteps: 4,
6666
supportsLoRA: true,
6767
},
68-
"sd-turbo": {
69-
name: "SDTurbo",
68+
"sdxl-turbo": {
69+
name: "SDXL Turbo",
7070
docsUrl:
7171
"",
7272
about:
@@ -79,10 +79,10 @@ export const PIPELINES: Record<string, PipelineInfo> = {
7979
defaultTemporalInterpolationMethod: "linear",
8080
defaultTemporalInterpolationSteps: 4,
8181
pipelineCompatibility: "cloud",
82-
cloudModelId: "stabilityai/sd-turbo",
82+
cloudModelId: "stabilityai/sdxl-turbo",
8383
},
84-
"sdxl-turbo": {
85-
name: "SDXL Turbo",
84+
"sd-turbo": {
85+
name: "SDTurbo",
8686
docsUrl:
8787
"",
8888
about:
@@ -95,7 +95,7 @@ export const PIPELINES: Record<string, PipelineInfo> = {
9595
defaultTemporalInterpolationMethod: "linear",
9696
defaultTemporalInterpolationSteps: 4,
9797
pipelineCompatibility: "cloud",
98-
cloudModelId: "stabilityai/sdxl-turbo",
98+
cloudModelId: "stabilityai/sd-turbo",
9999
},
100100
passthrough: {
101101
name: "Passthrough",

frontend/src/hooks/useStreamState.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ export function useStreamState() {
5454
const info = await getHardwareInfo();
5555
setHardwareInfo(info);
5656
} catch (error) {
57+
// TODO disable local gpu mode if this fails and only allow cloud?
5758
console.error("Failed to fetch hardware info:", error);
5859
}
5960
};

0 commit comments

Comments
 (0)