andito HF Staff commited on
Commit
1a8a72f
·
verified ·
1 Parent(s): e3b40cc

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +50 -14
app.py CHANGED
@@ -86,7 +86,6 @@ class GlobalState:
86
  def push_audio(self, audio_bytes: bytes):
87
  """
88
  Pushes raw audio bytes.
89
-
90
  If the queue is full (meaning we are lagging), throw away the OLDEST audio.
91
  """
92
  # Limit queue to ~0.5 seconds of audio (approx 5-6 chunks of 4096 bytes)
@@ -263,6 +262,29 @@ class MovementManager:
263
  print(f"Playback Error: {e}")
264
  self.is_playing = False
265
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
266
  manager = MovementManager()
267
 
268
 
@@ -289,6 +311,13 @@ async def robot_endpoint(ws: WebSocket):
289
  finally:
290
  state.robot_ws = None
291
 
 
 
 
 
 
 
 
292
  @app.websocket("/video_stream")
293
  async def stream_endpoint(ws: WebSocket):
294
  """Endpoint for Robot/Sim to send video frames."""
@@ -364,7 +393,6 @@ def webrtc_audio_generator():
364
  def webrtc_video_generator():
365
  """
366
  Generator for FastRTC WebRTC (mode='receive', modality='video').
367
-
368
  It reads JPEG bytes from state.latest_frame_bytes, decodes them with OpenCV,
369
  and yields HxWx3 uint8 frames as expected by FastRTC.
370
  """
@@ -437,17 +465,25 @@ with gr.Blocks(title="Reachy Controller", theme=gr.themes.Soft()) as demo:
437
 
438
  # --- RIGHT COLUMN: View ---
439
  with gr.Column(scale=2):
440
- robot_video = WebRTC(
441
- label="Robot Video",
442
- modality="video",
443
- mode="receive",
444
- )
445
- robot_video.stream(
446
- fn=lambda: webrtc_video_generator(),
447
- inputs=None,
448
- outputs=[robot_video],
449
- trigger=listen_btn.click,
450
- )
 
 
 
 
 
 
 
 
451
 
452
  # --- Movement Builders ---
453
  with gr.Tabs():
@@ -502,4 +538,4 @@ app = gr.mount_gradio_app(app, demo, path="/")
502
  if __name__ == "__main__":
503
  print("🚀 Server starting on http://0.0.0.0:7860")
504
  print("ℹ️ Point your Robot/Sim to: ws://<YOUR_PC_IP>:7860/robot")
505
- uvicorn.run(app, host="0.0.0.0", port=7860, proxy_headers=True, forwarded_allow_ips="*")
 
86
  def push_audio(self, audio_bytes: bytes):
87
  """
88
  Pushes raw audio bytes.
 
89
  If the queue is full (meaning we are lagging), throw away the OLDEST audio.
90
  """
91
  # Limit queue to ~0.5 seconds of audio (approx 5-6 chunks of 4096 bytes)
 
262
  print(f"Playback Error: {e}")
263
  self.is_playing = False
264
 
265
+ def generate_mjpeg_stream(self):
266
+ last_timestamp = 0.0
267
+
268
+ while True:
269
+ # 1. Check if frame has changed
270
+ with state.frame_lock:
271
+ current_bytes = state.latest_frame_bytes
272
+ current_timestamp = state.latest_frame_ts
273
+
274
+ # 2. Only yield if this is a new frame
275
+ if current_timestamp > last_timestamp:
276
+ last_timestamp = current_timestamp
277
+ if current_bytes is not None:
278
+ yield (b'--frame\r\n'
279
+ b'Content-Type: image/jpeg\r\n\r\n' + current_bytes + b'\r\n')
280
+ else:
281
+ # If no new frame, sleep a bit longer to save CPU
282
+ time.sleep(0.02)
283
+ continue
284
+
285
+ # Cap FPS slightly to prevent saturation
286
+ time.sleep(0.02)
287
+
288
  manager = MovementManager()
289
 
290
 
 
311
  finally:
312
  state.robot_ws = None
313
 
314
+ @app.get("/video_feed")
315
+ def video_feed():
316
+ return StreamingResponse(
317
+ manager.generate_mjpeg_stream(),
318
+ media_type="multipart/x-mixed-replace; boundary=frame"
319
+ )
320
+
321
  @app.websocket("/video_stream")
322
  async def stream_endpoint(ws: WebSocket):
323
  """Endpoint for Robot/Sim to send video frames."""
 
393
  def webrtc_video_generator():
394
  """
395
  Generator for FastRTC WebRTC (mode='receive', modality='video').
 
396
  It reads JPEG bytes from state.latest_frame_bytes, decodes them with OpenCV,
397
  and yields HxWx3 uint8 frames as expected by FastRTC.
398
  """
 
465
 
466
  # --- RIGHT COLUMN: View ---
467
  with gr.Column(scale=2):
468
+ # robot_video = WebRTC(
469
+ # label="Robot Video",
470
+ # modality="video",
471
+ # mode="receive",
472
+ # )
473
+ # robot_video.stream(
474
+ # fn=lambda: webrtc_video_generator(),
475
+ # inputs=None,
476
+ # outputs=[robot_video],
477
+ # trigger=listen_btn.click,
478
+ # )
479
+ html_code = """
480
+ <html>
481
+ <body>
482
+ <img src="/video_feed" style="width: 100%; max-width: 1080px; border-radius: 8px;">
483
+ </body>
484
+ </html>
485
+ """
486
+ sim_view = gr.HTML(value=html_code, label="🎬 Robot Simulation")
487
 
488
  # --- Movement Builders ---
489
  with gr.Tabs():
 
538
  if __name__ == "__main__":
539
  print("🚀 Server starting on http://0.0.0.0:7860")
540
  print("ℹ️ Point your Robot/Sim to: ws://<YOUR_PC_IP>:7860/robot")
541
+ uvicorn.run(app, host="0.0.0.0", port=7860, proxy_headers=True, forwarded_allow_ips="*")