Testimony Adekoya commited on
Commit
b828bd1
·
1 Parent(s): 42e8aa3

Fizing TURN server using Twilio

Browse files
Files changed (1) hide show
  1. pages/1_Live_Detection.py +41 -21
pages/1_Live_Detection.py CHANGED
@@ -22,9 +22,15 @@ def load_app_config():
22
  config_path = "/config.yaml" if os.path.exists("/config.yaml") else "config.yaml"
23
  with open(config_path, 'r') as f:
24
  config = yaml.safe_load(f)
25
- return config, gemini_api_key
 
 
 
 
 
 
26
 
27
- config, gemini_api_key = load_app_config()
28
 
29
  # --- Initialize Session State (if not already done in main.py) ---
30
  if "play_audio" not in st.session_state:
@@ -45,9 +51,11 @@ def autoplay_audio(audio_bytes: bytes):
45
 
46
  # --- WebRTC Video Processor ---
47
  class VideoProcessor(VideoProcessorBase):
48
- def __init__(self):
 
 
49
  self._detector = get_detector(config)
50
- self._alerter = get_alerter(config, gemini_api_key)
51
 
52
  def recv(self, frame: av.VideoFrame) -> av.VideoFrame:
53
  img = frame.to_ndarray(format="bgr24")
@@ -55,37 +63,46 @@ class VideoProcessor(VideoProcessorBase):
55
  strategy = config.get('detection_strategy')
56
  if strategy == 'hybrid':
57
  processed_frame, alert_triggered, active_alerts = self._detector.process_frame(img)
58
- st.session_state.active_alerts = active_alerts if alert_triggered else {"status": "Awake"}
59
- else: # Fallback for simpler strategies
60
  processed_frame, indicators = self._detector.process_frame(img)
61
- alert_triggered = any(indicators.values())
62
- st.session_state.active_alerts = indicators if alert_triggered else {"status": "Awake"}
63
 
64
  if alert_triggered:
65
  audio_data = self._alerter.trigger_alert()
66
  if audio_data:
67
- st.session_state.play_audio = audio_data
68
  else:
69
  self._alerter.reset_alert()
70
 
71
  return av.VideoFrame.from_ndarray(processed_frame, format="bgr24")
72
-
73
  # --- Page UI ---
74
  # The st.set_page_config() call has been removed from this file.
75
  # The configuration from main.py will apply to this page.
76
  st.title("📹 Live Drowsiness Detection")
77
  st.info("Press 'START' to activate your camera and begin monitoring.")
78
 
79
- # --- Robust RTC Configuration ---
80
- # Provide a list of STUN servers for better reliability.
81
- RTC_CONFIGURATION = RTCConfiguration({
82
- "iceServers": [
83
- {"urls": ["stun:stun.l.google.com:19302"]},
84
- {"urls": ["stun:stun1.l.google.com:19302"]},
85
- {"urls": ["stun:stun2.l.google.com:19302"]},
86
- {"urls": ["stun:stun.services.mozilla.com:3478"]},
 
 
 
 
 
 
 
87
  ]
88
- })
 
 
89
 
90
 
91
  col1, col2 = st.columns([3, 1])
@@ -93,8 +110,11 @@ col1, col2 = st.columns([3, 1])
93
  with col1:
94
  webrtc_ctx = webrtc_streamer(
95
  key="drowsiness-detection",
96
- video_processor_factory=VideoProcessor,
97
- rtc_configuration=RTC_CONFIGURATION, # Use the new robust configuration
 
 
 
98
  media_stream_constraints={"video": True, "audio": False},
99
  async_processing=True,
100
  )
 
22
  config_path = "/config.yaml" if os.path.exists("/config.yaml") else "config.yaml"
23
  with open(config_path, 'r') as f:
24
  config = yaml.safe_load(f)
25
+ # Load secrets from environment
26
+ secrets = {
27
+ "gemini_api_key": os.getenv("GEMINI_API_KEY"),
28
+ "turn_username": os.getenv("TURN_USERNAME"),
29
+ "turn_credential": os.getenv("TURN_CREDENTIAL")
30
+ }
31
+ return config, secrets
32
 
33
+ config, secrets = load_app_config()
34
 
35
  # --- Initialize Session State (if not already done in main.py) ---
36
  if "play_audio" not in st.session_state:
 
51
 
52
  # --- WebRTC Video Processor ---
53
  class VideoProcessor(VideoProcessorBase):
54
+ def __init__(self, status_queue: queue.Queue, audio_queue: queue.Queue):
55
+ self.status_queue = status_queue
56
+ self.audio_queue = audio_queue
57
  self._detector = get_detector(config)
58
+ self._alerter = get_alerter(config, secrets["gemini_api_key"])
59
 
60
  def recv(self, frame: av.VideoFrame) -> av.VideoFrame:
61
  img = frame.to_ndarray(format="bgr24")
 
63
  strategy = config.get('detection_strategy')
64
  if strategy == 'hybrid':
65
  processed_frame, alert_triggered, active_alerts = self._detector.process_frame(img)
66
+ self.status_queue.put(active_alerts if alert_triggered or 'Low Light' in active_alerts else {"status": "Awake"})
67
+ else:
68
  processed_frame, indicators = self._detector.process_frame(img)
69
+ alert_triggered = any(v for k, v in indicators.items() if k != 'low_light')
70
+ self.status_queue.put(indicators)
71
 
72
  if alert_triggered:
73
  audio_data = self._alerter.trigger_alert()
74
  if audio_data:
75
+ self.audio_queue.put(audio_data)
76
  else:
77
  self._alerter.reset_alert()
78
 
79
  return av.VideoFrame.from_ndarray(processed_frame, format="bgr24")
80
+
81
  # --- Page UI ---
82
  # The st.set_page_config() call has been removed from this file.
83
  # The configuration from main.py will apply to this page.
84
  st.title("📹 Live Drowsiness Detection")
85
  st.info("Press 'START' to activate your camera and begin monitoring.")
86
 
87
+ # --- Dynamically Build RTC Configuration ---
88
+ ice_servers = [{'urls': 'stun:global.stun.twilio.com:3478'}]
89
+ if secrets["turn_username"] and secrets["turn_credential"]:
90
+ print("TURN credentials found, adding TURN servers to config.")
91
+ turn_servers = [
92
+ {
93
+ 'urls': 'turn:global.turn.twilio.com:3478?transport=udp',
94
+ 'username': secrets["turn_username"],
95
+ 'credential': secrets["turn_credential"]
96
+ },
97
+ {
98
+ 'urls': 'turn:global.turn.twilio.com:3478?transport=tcp',
99
+ 'username': secrets["turn_username"],
100
+ 'credential': secrets["turn_credential"]
101
+ }
102
  ]
103
+ ice_servers.extend(turn_servers)
104
+
105
+ RTC_CONFIGURATION = RTCConfiguration({"iceServers": ice_servers})
106
 
107
 
108
  col1, col2 = st.columns([3, 1])
 
110
  with col1:
111
  webrtc_ctx = webrtc_streamer(
112
  key="drowsiness-detection",
113
+ video_processor_factory=lambda: VideoProcessor(
114
+ status_queue=st.session_state.status_queue,
115
+ audio_queue=st.session_state.audio_queue
116
+ ),
117
+ rtc_configuration=RTC_CONFIGURATION,
118
  media_stream_constraints={"video": True, "audio": False},
119
  async_processing=True,
120
  )