Spaces:
Running
on
A100
Running
on
A100
fix timeout/queue message
Browse files- app_init.py +13 -13
- frontend/src/lib/components/Warning.svelte +27 -0
- frontend/src/lib/lcmLive.ts +2 -3
- frontend/src/routes/+page.svelte +22 -12
app_init.py
CHANGED
@@ -41,7 +41,6 @@ def init_app(app: FastAPI, user_data: UserData, args: Args, pipeline):
|
|
41 |
try:
|
42 |
user_id = uuid.uuid4()
|
43 |
print(f"New user connected: {user_id}")
|
44 |
-
|
45 |
await user_data.create_user(user_id, websocket)
|
46 |
await websocket.send_json(
|
47 |
{"status": "connected", "message": "Connected", "userId": str(user_id)}
|
@@ -61,6 +60,16 @@ def init_app(app: FastAPI, user_data: UserData, args: Args, pipeline):
|
|
61 |
last_time = time.time()
|
62 |
try:
|
63 |
while True:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
64 |
data = await websocket.receive_json()
|
65 |
if data["status"] != "next_frame":
|
66 |
asyncio.sleep(THROTTLE)
|
@@ -74,21 +83,11 @@ def init_app(app: FastAPI, user_data: UserData, args: Args, pipeline):
|
|
74 |
image_data = await websocket.receive_bytes()
|
75 |
if len(image_data) == 0:
|
76 |
await websocket.send_json({"status": "send_frame"})
|
|
|
77 |
continue
|
78 |
params.image = bytes_to_pil(image_data)
|
79 |
await user_data.update_data(user_id, params)
|
80 |
await websocket.send_json({"status": "wait"})
|
81 |
-
if args.timeout > 0 and time.time() - last_time > args.timeout:
|
82 |
-
await websocket.send_json(
|
83 |
-
{
|
84 |
-
"status": "timeout",
|
85 |
-
"message": "Your session has ended",
|
86 |
-
"userId": user_id,
|
87 |
-
}
|
88 |
-
)
|
89 |
-
await websocket.close()
|
90 |
-
return
|
91 |
-
await asyncio.sleep(THROTTLE)
|
92 |
|
93 |
except Exception as e:
|
94 |
logging.error(f"Error: {e}")
|
@@ -102,7 +101,6 @@ def init_app(app: FastAPI, user_data: UserData, args: Args, pipeline):
|
|
102 |
@app.get("/api/stream/{user_id}")
|
103 |
async def stream(user_id: uuid.UUID, request: Request):
|
104 |
try:
|
105 |
-
print(f"New stream request: {user_id}")
|
106 |
|
107 |
async def generate():
|
108 |
websocket = user_data.get_websocket(user_id)
|
@@ -112,6 +110,7 @@ def init_app(app: FastAPI, user_data: UserData, args: Args, pipeline):
|
|
112 |
params = await user_data.get_latest_data(user_id)
|
113 |
if not vars(params) or params.__dict__ == last_params.__dict__:
|
114 |
await websocket.send_json({"status": "send_frame"})
|
|
|
115 |
continue
|
116 |
|
117 |
last_params = params
|
@@ -119,6 +118,7 @@ def init_app(app: FastAPI, user_data: UserData, args: Args, pipeline):
|
|
119 |
|
120 |
if image is None:
|
121 |
await websocket.send_json({"status": "send_frame"})
|
|
|
122 |
continue
|
123 |
frame = pil_to_frame(image)
|
124 |
yield frame
|
|
|
41 |
try:
|
42 |
user_id = uuid.uuid4()
|
43 |
print(f"New user connected: {user_id}")
|
|
|
44 |
await user_data.create_user(user_id, websocket)
|
45 |
await websocket.send_json(
|
46 |
{"status": "connected", "message": "Connected", "userId": str(user_id)}
|
|
|
60 |
last_time = time.time()
|
61 |
try:
|
62 |
while True:
|
63 |
+
if args.timeout > 0 and time.time() - last_time > args.timeout:
|
64 |
+
await websocket.send_json(
|
65 |
+
{
|
66 |
+
"status": "timeout",
|
67 |
+
"message": "Your session has ended",
|
68 |
+
"userId": str(user_id),
|
69 |
+
}
|
70 |
+
)
|
71 |
+
await websocket.close()
|
72 |
+
return
|
73 |
data = await websocket.receive_json()
|
74 |
if data["status"] != "next_frame":
|
75 |
asyncio.sleep(THROTTLE)
|
|
|
83 |
image_data = await websocket.receive_bytes()
|
84 |
if len(image_data) == 0:
|
85 |
await websocket.send_json({"status": "send_frame"})
|
86 |
+
await asyncio.sleep(THROTTLE)
|
87 |
continue
|
88 |
params.image = bytes_to_pil(image_data)
|
89 |
await user_data.update_data(user_id, params)
|
90 |
await websocket.send_json({"status": "wait"})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
91 |
|
92 |
except Exception as e:
|
93 |
logging.error(f"Error: {e}")
|
|
|
101 |
@app.get("/api/stream/{user_id}")
|
102 |
async def stream(user_id: uuid.UUID, request: Request):
|
103 |
try:
|
|
|
104 |
|
105 |
async def generate():
|
106 |
websocket = user_data.get_websocket(user_id)
|
|
|
110 |
params = await user_data.get_latest_data(user_id)
|
111 |
if not vars(params) or params.__dict__ == last_params.__dict__:
|
112 |
await websocket.send_json({"status": "send_frame"})
|
113 |
+
await asyncio.sleep(THROTTLE)
|
114 |
continue
|
115 |
|
116 |
last_params = params
|
|
|
118 |
|
119 |
if image is None:
|
120 |
await websocket.send_json({"status": "send_frame"})
|
121 |
+
await asyncio.sleep(THROTTLE)
|
122 |
continue
|
123 |
frame = pil_to_frame(image)
|
124 |
yield frame
|
frontend/src/lib/components/Warning.svelte
ADDED
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<script lang="ts">
|
2 |
+
export let message: string = '';
|
3 |
+
|
4 |
+
let timeout = 0;
|
5 |
+
$: if (message !== '') {
|
6 |
+
console.log('message', message);
|
7 |
+
clearTimeout(timeout);
|
8 |
+
timeout = setTimeout(() => {
|
9 |
+
message = '';
|
10 |
+
}, 5000);
|
11 |
+
}
|
12 |
+
</script>
|
13 |
+
|
14 |
+
{#if message}
|
15 |
+
<div class="fixed right-0 top-0 m-4 cursor-pointer" on:click={() => (message = '')}>
|
16 |
+
<div class="rounded bg-red-800 p-4 text-white">
|
17 |
+
{message}
|
18 |
+
</div>
|
19 |
+
<div class="bar transition-all duration-500" style="width: 0;"></div>
|
20 |
+
</div>
|
21 |
+
{/if}
|
22 |
+
|
23 |
+
<style lang="postcss" scoped>
|
24 |
+
.button {
|
25 |
+
@apply rounded bg-gray-700 font-normal text-white hover:bg-gray-800 disabled:cursor-not-allowed disabled:bg-gray-300 dark:disabled:bg-gray-700 dark:disabled:text-black;
|
26 |
+
}
|
27 |
+
</style>
|
frontend/src/lib/lcmLive.ts
CHANGED
@@ -40,7 +40,6 @@ export const lcmLiveActions = {
|
|
40 |
const userId = data.userId;
|
41 |
lcmLiveStatus.set(LCMLiveStatus.CONNECTED);
|
42 |
streamId.set(userId);
|
43 |
-
resolve(userId);
|
44 |
break;
|
45 |
case "send_frame":
|
46 |
lcmLiveStatus.set(LCMLiveStatus.SEND_FRAME);
|
@@ -57,12 +56,12 @@ export const lcmLiveActions = {
|
|
57 |
console.log("timeout");
|
58 |
lcmLiveStatus.set(LCMLiveStatus.DISCONNECTED);
|
59 |
streamId.set(null);
|
60 |
-
|
61 |
case "error":
|
62 |
console.log(data.message);
|
63 |
lcmLiveStatus.set(LCMLiveStatus.DISCONNECTED);
|
64 |
streamId.set(null);
|
65 |
-
reject(data.message);
|
66 |
}
|
67 |
};
|
68 |
|
|
|
40 |
const userId = data.userId;
|
41 |
lcmLiveStatus.set(LCMLiveStatus.CONNECTED);
|
42 |
streamId.set(userId);
|
|
|
43 |
break;
|
44 |
case "send_frame":
|
45 |
lcmLiveStatus.set(LCMLiveStatus.SEND_FRAME);
|
|
|
56 |
console.log("timeout");
|
57 |
lcmLiveStatus.set(LCMLiveStatus.DISCONNECTED);
|
58 |
streamId.set(null);
|
59 |
+
resolve({ status: "timeout" });
|
60 |
case "error":
|
61 |
console.log(data.message);
|
62 |
lcmLiveStatus.set(LCMLiveStatus.DISCONNECTED);
|
63 |
streamId.set(null);
|
64 |
+
reject(new Error(data.message));
|
65 |
}
|
66 |
};
|
67 |
|
frontend/src/routes/+page.svelte
CHANGED
@@ -7,6 +7,7 @@
|
|
7 |
import Button from '$lib/components/Button.svelte';
|
8 |
import PipelineOptions from '$lib/components/PipelineOptions.svelte';
|
9 |
import Spinner from '$lib/icons/spinner.svelte';
|
|
|
10 |
import { lcmLiveStatus, lcmLiveActions, LCMLiveStatus } from '$lib/lcmLive';
|
11 |
import { mediaStreamActions, onFrameChangeStore } from '$lib/mediaStream';
|
12 |
import { getPipelineValues, deboucedPipelineValues } from '$lib/store';
|
@@ -18,6 +19,7 @@
|
|
18 |
let maxQueueSize: number = 0;
|
19 |
let currentQueueSize: number = 0;
|
20 |
let queueCheckerRunning: boolean = false;
|
|
|
21 |
|
22 |
onMount(() => {
|
23 |
getSettings();
|
@@ -60,20 +62,27 @@
|
|
60 |
|
61 |
let disabled = false;
|
62 |
async function toggleLcmLive() {
|
63 |
-
|
64 |
-
if (
|
65 |
-
|
66 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
67 |
}
|
68 |
-
|
69 |
-
|
70 |
disabled = false;
|
71 |
-
toggleQueueChecker(false);
|
72 |
-
} else {
|
73 |
-
if (isImageMode) {
|
74 |
-
mediaStreamActions.stop();
|
75 |
-
}
|
76 |
-
lcmLiveActions.stop();
|
77 |
toggleQueueChecker(true);
|
78 |
}
|
79 |
}
|
@@ -86,6 +95,7 @@
|
|
86 |
</svelte:head>
|
87 |
|
88 |
<main class="container mx-auto flex max-w-5xl flex-col gap-3 px-4 py-4">
|
|
|
89 |
<article class="text-center">
|
90 |
{#if pageContent}
|
91 |
{@html pageContent}
|
|
|
7 |
import Button from '$lib/components/Button.svelte';
|
8 |
import PipelineOptions from '$lib/components/PipelineOptions.svelte';
|
9 |
import Spinner from '$lib/icons/spinner.svelte';
|
10 |
+
import Warning from '$lib/components/Warning.svelte';
|
11 |
import { lcmLiveStatus, lcmLiveActions, LCMLiveStatus } from '$lib/lcmLive';
|
12 |
import { mediaStreamActions, onFrameChangeStore } from '$lib/mediaStream';
|
13 |
import { getPipelineValues, deboucedPipelineValues } from '$lib/store';
|
|
|
19 |
let maxQueueSize: number = 0;
|
20 |
let currentQueueSize: number = 0;
|
21 |
let queueCheckerRunning: boolean = false;
|
22 |
+
let warningMessage: string = '';
|
23 |
|
24 |
onMount(() => {
|
25 |
getSettings();
|
|
|
62 |
|
63 |
let disabled = false;
|
64 |
async function toggleLcmLive() {
|
65 |
+
try {
|
66 |
+
if (!isLCMRunning) {
|
67 |
+
if (isImageMode) {
|
68 |
+
await mediaStreamActions.enumerateDevices();
|
69 |
+
await mediaStreamActions.start();
|
70 |
+
}
|
71 |
+
disabled = true;
|
72 |
+
await lcmLiveActions.start(getSreamdata);
|
73 |
+
warningMessage = 'Timeout, please try again.';
|
74 |
+
disabled = false;
|
75 |
+
toggleQueueChecker(false);
|
76 |
+
} else {
|
77 |
+
if (isImageMode) {
|
78 |
+
mediaStreamActions.stop();
|
79 |
+
}
|
80 |
+
lcmLiveActions.stop();
|
81 |
+
toggleQueueChecker(true);
|
82 |
}
|
83 |
+
} catch (e) {
|
84 |
+
warningMessage = e instanceof Error ? e.message : '';
|
85 |
disabled = false;
|
|
|
|
|
|
|
|
|
|
|
|
|
86 |
toggleQueueChecker(true);
|
87 |
}
|
88 |
}
|
|
|
95 |
</svelte:head>
|
96 |
|
97 |
<main class="container mx-auto flex max-w-5xl flex-col gap-3 px-4 py-4">
|
98 |
+
<Warning bind:message={warningMessage}></Warning>
|
99 |
<article class="text-center">
|
100 |
{#if pageContent}
|
101 |
{@html pageContent}
|