AnimeOverlord commited on
Commit
6594660
·
1 Parent(s): accd6c8

still initial commit

Browse files
Files changed (1) hide show
  1. app.py +28 -28
app.py CHANGED
@@ -3,35 +3,34 @@ import gradio as gr
3
  import cv2
4
  import numpy as np
5
  import modal
6
-
7
  # ── Authentication & Modal Connection ───────────────────────────────────────
8
- # Modal automatically authenticates using MODAL_TOKEN_ID and MODAL_TOKEN_SECRET
9
- # from the environment. We check them here to ensure your HF Secrets are loaded.
10
-
11
  token_id = os.environ.get("MODAL_TOKEN_ID")
12
  token_secret = os.environ.get("MODAL_TOKEN_SECRET")
 
13
 
14
- if not token_id or not token_secret:
 
15
  print("⚠️ [AUTH ERROR] Modal tokens missing! Check your Hugging Face Secrets.")
16
- voxel_backend = None
17
- status_text = "🔴 Offline (Missing Tokens)"
18
- else:
19
- try:
20
- print("🔑 Tokens found. Connecting to Modal...")
21
- # Hook directly into your remote Modal class
 
 
 
22
  VoxelModelCls = modal.Cls.from_name("flux-klein-voxel-backend", "VoxelModel")
23
- voxel_backend = VoxelModelCls().process_frame
24
- status_text = "🟢 Connected"
25
  print("✅ Successfully connected to Modal backend.")
26
- except Exception as e:
27
- print(f"❌ Failed to connect to Modal: {e}")
28
- voxel_backend = None
29
- status_text = "🔴 Offline (Connection Error)"
30
 
31
  # ── Core Backend Execution ──────────────────────────────────────────────────
32
- async def run_modal_backend(frame: np.ndarray) -> np.ndarray:
33
  """Compresses the frame, sends it to Modal, and decodes the returned bytes."""
34
- if voxel_backend is None:
 
35
  return frame
36
 
37
  # Compress to JPEG to save network bandwidth
@@ -40,8 +39,8 @@ async def run_modal_backend(frame: np.ndarray) -> np.ndarray:
40
  return frame
41
 
42
  try:
43
- # Fire bytes to Modal serverless container ASYNCHRONOUSLY
44
- processed_bytes = await voxel_backend.remote.aio(encoded.tobytes())
45
  # Decode the returning bytes back into an OpenCV image
46
  result = cv2.imdecode(np.frombuffer(processed_bytes, dtype=np.uint8), cv2.IMREAD_COLOR)
47
  return result if result is not None else frame
@@ -55,18 +54,19 @@ async def run_modal_backend(frame: np.ndarray) -> np.ndarray:
55
 
56
 
57
  # ── Activation & Pre-Warming Logic ──────────────────────────────────────────
58
- async def start_and_warmup_container():
59
  """Forces the Modal container to start up before enabling the webcam stream."""
60
  print("🚀 [START CLICKED] Waking up Modal container to prevent cold-start lag...")
61
 
62
- if voxel_backend is not None:
 
63
  try:
64
  # Create a tiny 1x1 blank image payload
65
  dummy_frame = np.zeros((1, 1, 3), dtype=np.uint8)
66
  success, encoded = cv2.imencode(".jpg", dummy_frame)
67
  if success:
68
- # Trigger a remote execution to force container ignition ASYNCHRONOUSLY
69
- await voxel_backend.remote.aio(encoded.tobytes())
70
  print("✅ [CONTAINER READY] Modal container is hot and ready for frames.")
71
  except Exception as e:
72
  print(f"ℹ️ [CONTAINER NOTIFICATION] Warmup call dispatched: {e}")
@@ -75,7 +75,7 @@ async def start_and_warmup_container():
75
 
76
 
77
  # ── Streaming Logic ─────────────────────────────────────────────────────────
78
- async def process_video_stream(frame: np.ndarray, mode: str, is_running: bool) -> np.ndarray:
79
  """Handles the webcam feed and respects the Start/Stop toggle."""
80
  if frame is None:
81
  return None
@@ -85,8 +85,8 @@ async def process_video_stream(frame: np.ndarray, mode: str, is_running: bool) -
85
  if not is_running:
86
  return frame
87
 
88
- # 1. Process the frame through the Modal network (AWAIT IT)
89
- processed = await run_modal_backend(frame)
90
 
91
  # 2. Format the output based on the selected UI mode
92
  if mode == "Minecraft Filter":
 
3
  import cv2
4
  import numpy as np
5
  import modal
 
6
  # ── Authentication & Modal Connection ───────────────────────────────────────
 
 
 
7
  token_id = os.environ.get("MODAL_TOKEN_ID")
8
  token_secret = os.environ.get("MODAL_TOKEN_SECRET")
9
+ has_tokens = bool(token_id and token_secret)
10
 
11
+ status_text = "🟢 Ready" if has_tokens else "🔴 Offline (Missing Tokens)"
12
+ if not has_tokens:
13
  print("⚠️ [AUTH ERROR] Modal tokens missing! Check your Hugging Face Secrets.")
14
+
15
+ # Cache to prevent Python 3.13 cross-thread loop crashes
16
+ _voxel_backend = None
17
+
18
+ def get_modal_backend():
19
+ """Lazy-loads the Modal client inside the execution thread to protect the event loop."""
20
+ global _voxel_backend
21
+ if _voxel_backend is None and has_tokens:
22
+ print("🔑 Connecting to Modal...")
23
  VoxelModelCls = modal.Cls.from_name("flux-klein-voxel-backend", "VoxelModel")
24
+ _voxel_backend = VoxelModelCls().process_frame
 
25
  print("✅ Successfully connected to Modal backend.")
26
+ return _voxel_backend
27
+
 
 
28
 
29
  # ── Core Backend Execution ──────────────────────────────────────────────────
30
+ def run_modal_backend(frame: np.ndarray) -> np.ndarray:
31
  """Compresses the frame, sends it to Modal, and decodes the returned bytes."""
32
+ backend = get_modal_backend()
33
+ if backend is None:
34
  return frame
35
 
36
  # Compress to JPEG to save network bandwidth
 
39
  return frame
40
 
41
  try:
42
+ # Fire bytes to Modal serverless container
43
+ processed_bytes = backend.remote(encoded.tobytes())
44
  # Decode the returning bytes back into an OpenCV image
45
  result = cv2.imdecode(np.frombuffer(processed_bytes, dtype=np.uint8), cv2.IMREAD_COLOR)
46
  return result if result is not None else frame
 
54
 
55
 
56
  # ── Activation & Pre-Warming Logic ──────────────────────────────────────────
57
+ def start_and_warmup_container():
58
  """Forces the Modal container to start up before enabling the webcam stream."""
59
  print("🚀 [START CLICKED] Waking up Modal container to prevent cold-start lag...")
60
 
61
+ backend = get_modal_backend()
62
+ if backend is not None:
63
  try:
64
  # Create a tiny 1x1 blank image payload
65
  dummy_frame = np.zeros((1, 1, 3), dtype=np.uint8)
66
  success, encoded = cv2.imencode(".jpg", dummy_frame)
67
  if success:
68
+ # Trigger a remote execution to force container ignition
69
+ backend.remote(encoded.tobytes())
70
  print("✅ [CONTAINER READY] Modal container is hot and ready for frames.")
71
  except Exception as e:
72
  print(f"ℹ️ [CONTAINER NOTIFICATION] Warmup call dispatched: {e}")
 
75
 
76
 
77
  # ── Streaming Logic ─────────────────────────────────────────────────────────
78
+ def process_video_stream(frame: np.ndarray, mode: str, is_running: bool) -> np.ndarray:
79
  """Handles the webcam feed and respects the Start/Stop toggle."""
80
  if frame is None:
81
  return None
 
85
  if not is_running:
86
  return frame
87
 
88
+ # 1. Process the frame through the Modal network
89
+ processed = run_modal_backend(frame)
90
 
91
  # 2. Format the output based on the selected UI mode
92
  if mode == "Minecraft Filter":