Spaces:
Runtime error
Runtime error
File size: 7,164 Bytes
cb92d2b 246efdb cb92d2b 1123781 cb92d2b 246efdb 46bd9ac 43148fd 246efdb 466d3e0 46bd9ac c56b1e5 246efdb c56b1e5 c01188e c56b1e5 246efdb c01188e be0215c 1123781 246efdb 1d3190d 0e617d2 ff9325e 246efdb bea2d0b 246efdb 9a8789a 246efdb 9a8789a 246efdb 9a8789a 246efdb ff9325e 78b5416 9a8789a 78b5416 bea2d0b 9a8789a 246efdb 78b5416 bea2d0b 9a8789a bea2d0b 9a8789a 78b5416 9a8789a bea2d0b 9a8789a 78b5416 d6fedfa 78b5416 246efdb be97094 c56b1e5 ff9325e bea2d0b 9a8789a 246efdb bea2d0b 9a8789a bea2d0b 9a8789a 246efdb 9a8789a 246efdb 9a8789a cb92d2b 2398f39 d1f4c77 78b5416 c01188e 46bd9ac 246efdb 46bd9ac 0b5ceff d6fedfa 246efdb d6fedfa bea2d0b 9a8789a bea2d0b 246efdb 9a8789a cb92d2b 43148fd 53948e4 d1f4c77 53948e4 46bd9ac d1f4c77 246efdb d1f4c77 53948e4 246efdb 9a8789a 6a5df00 d1f4c77 cefdf75 43148fd 246efdb 43148fd cb92d2b 246efdb cb92d2b |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 |
<script lang="ts">
import { onMount } from "svelte";
import type { Fields, PipelineInfo } from "$lib/types";
import { PipelineMode } from "$lib/types";
import ImagePlayer from "$lib/components/ImagePlayer.svelte";
import VideoInput from "$lib/components/VideoInput.svelte";
import Button from "$lib/components/Button.svelte";
import PipelineOptions from "$lib/components/PipelineOptions.svelte";
import Spinner from "$lib/icons/spinner.svelte";
import Warning from "$lib/components/Warning.svelte";
import { lcmLiveStatus, lcmLiveActions, LCMLiveStatus } from "$lib/lcmLive";
import { mediaStreamActions, onFrameChangeStore } from "$lib/mediaStream";
import { getPipelineValues, deboucedPipelineValues } from "$lib/store";
let pipelineParams: Fields | undefined = $state();
let pipelineInfo: PipelineInfo | undefined = $state();
let pageContent: string | undefined = $state();
let isImageMode: boolean = $state(false);
let maxQueueSize: number = $state(0);
let currentQueueSize: number = $state(0);
let disabled: boolean = $state(false);
let queueCheckerRunning: boolean = $state(false);
let warningMessage: string = $state("");
onMount(() => {
getSettings();
});
async function getSettings() {
const settings = await fetch("/api/settings").then((r) => r.json());
pipelineParams = settings.input_params.properties;
pipelineInfo = settings.info.properties;
isImageMode = pipelineInfo?.input_mode?.default === PipelineMode.IMAGE;
maxQueueSize = settings.max_queue_size;
pageContent = settings.page_content;
toggleQueueChecker(true);
console.log(pipelineParams);
}
function toggleQueueChecker(start: boolean) {
queueCheckerRunning = start && maxQueueSize > 0;
if (start) {
getQueueSize();
}
}
async function getQueueSize() {
if (!queueCheckerRunning) {
return;
}
const data = await fetch("/api/queue").then((r) => r.json());
currentQueueSize = data.queue_size;
setTimeout(getQueueSize, 10000);
}
function getSreamdata():
| [Record<string, unknown>]
| [Record<string, unknown>, Blob] {
if (isImageMode) {
return [getPipelineValues(), $onFrameChangeStore?.blob];
} else {
return [$deboucedPipelineValues];
}
}
const isLCMRunning = $derived(
$lcmLiveStatus !== LCMLiveStatus.DISCONNECTED &&
$lcmLiveStatus !== LCMLiveStatus.ERROR,
);
const isConnecting = $derived($lcmLiveStatus === LCMLiveStatus.CONNECTING);
$effect(() => {
// Set warning messages based on lcmLiveStatus
if ($lcmLiveStatus === LCMLiveStatus.TIMEOUT) {
warningMessage = "Session timed out. Please try again.";
} else if ($lcmLiveStatus === LCMLiveStatus.ERROR) {
warningMessage = "Connection error occurred. Please try again.";
}
});
async function toggleLcmLive() {
try {
if (!isLCMRunning) {
if (isConnecting) {
return; // Don't allow multiple connection attempts
}
// Clear any previous warning messages
warningMessage = "";
disabled = true;
try {
if (isImageMode) {
await mediaStreamActions.enumerateDevices();
await mediaStreamActions.start();
}
await lcmLiveActions.start(getSreamdata);
toggleQueueChecker(false);
} finally {
// Always re-enable the button even if there was an error
disabled = false;
}
} else {
// Handle stopping - disable button during this process too
disabled = true;
try {
if (isImageMode) {
mediaStreamActions.stop();
}
await lcmLiveActions.stop();
toggleQueueChecker(true);
} finally {
disabled = false;
}
}
} catch (e) {
console.error("Error in toggleLcmLive:", e);
warningMessage =
e instanceof Error ? e.message : "An unknown error occurred";
disabled = false;
toggleQueueChecker(true);
}
}
// Reconnect function for automatic reconnection
async function reconnect() {
try {
disabled = true;
warningMessage = "Reconnecting...";
if (isImageMode) {
await mediaStreamActions.stop();
await mediaStreamActions.enumerateDevices();
await mediaStreamActions.start();
}
await lcmLiveActions.reconnect(getSreamdata);
warningMessage = "";
toggleQueueChecker(false);
} catch (e) {
warningMessage = e instanceof Error ? e.message : "Reconnection failed";
toggleQueueChecker(true);
} finally {
disabled = false;
}
}
</script>
<svelte:head>
<script
src="https://cdnjs.cloudflare.com/ajax/libs/iframe-resizer/4.3.9/iframeResizer.contentWindow.min.js"
></script>
</svelte:head>
<main class="container mx-auto flex max-w-5xl flex-col gap-3 px-4 py-4">
<Warning bind:message={warningMessage}></Warning>
<article class="text-center">
{#if pageContent}
<!-- eslint-disable-next-line svelte/no-at-html-tags -->
{@html pageContent}
{/if}
{#if maxQueueSize > 0}
<p class="text-sm">
There are <span id="queue_size" class="font-bold"
>{currentQueueSize}</span
>
user(s) sharing the same GPU, affecting real-time performance. Maximum queue
size is {maxQueueSize}.
<a
href="https://huggingface.co/spaces/radames/Real-Time-Latent-Consistency-Model?duplicate=true"
target="_blank"
class="text-blue-500 underline hover:no-underline">Duplicate</a
> and run it on your own GPU.
</p>
{/if}
{#if $lcmLiveStatus === LCMLiveStatus.ERROR}
<p class="mt-2 text-sm">
<button
class="text-blue-500 underline hover:no-underline"
onclick={reconnect}
{disabled}
>
Try reconnecting
</button>
</p>
{/if}
</article>
{#if pipelineParams}
<article class="my-3 grid grid-cols-1 gap-3 sm:grid-cols-4">
{#if isImageMode}
<div class="col-span-2 sm:col-start-1">
<VideoInput
width={Number(pipelineParams.width.default)}
height={Number(pipelineParams.height.default)}
></VideoInput>
</div>
{/if}
<div class={isImageMode ? "col-span-2 sm:col-start-3" : "col-span-4"}>
<ImagePlayer />
</div>
<div class="sm:col-span-4 sm:row-start-2">
<Button onclick={toggleLcmLive} {disabled} class="my-1 p-2 text-lg">
{#if isConnecting}
Connecting...
{:else if isLCMRunning}
Stop
{:else}
Start
{/if}
</Button>
<PipelineOptions {pipelineParams}></PipelineOptions>
</div>
</article>
{:else}
<!-- loading -->
<div class="flex items-center justify-center gap-3 py-48 text-2xl">
<Spinner class="animate-spin opacity-50"></Spinner>
<p>Loading...</p>
</div>
{/if}
</main>
<style lang="postcss">
@reference "tailwindcss";
:global(html) {
@apply text-black dark:bg-gray-900 dark:text-white;
}
</style>
|