Spaces:
Sleeping
Sleeping
Testimony Adekoya
commited on
Commit
·
f4fd68f
1
Parent(s):
b94e066
Pushing code for rtc loading
Browse files- pages/1_Live_Detection.py +37 -46
pages/1_Live_Detection.py
CHANGED
@@ -17,8 +17,6 @@ from src.alerting.alert_system import get_alerter
|
|
17 |
def load_app_config():
|
18 |
"""Loads config from yaml and .env files."""
|
19 |
load_dotenv()
|
20 |
-
gemini_api_key = os.getenv("GEMINI_API_KEY")
|
21 |
-
# Navigate up to the root to find the config file
|
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)
|
@@ -32,11 +30,11 @@ def load_app_config():
|
|
32 |
|
33 |
config, secrets = load_app_config()
|
34 |
|
35 |
-
# --- Initialize Session State
|
36 |
-
if "
|
37 |
-
st.session_state.
|
38 |
-
if "
|
39 |
-
st.session_state.
|
40 |
|
41 |
# --- Client-Side Audio Playback Function ---
|
42 |
def autoplay_audio(audio_bytes: bytes):
|
@@ -51,7 +49,10 @@ def autoplay_audio(audio_bytes: bytes):
|
|
51 |
|
52 |
# --- WebRTC Video Processor ---
|
53 |
class VideoProcessor(VideoProcessorBase):
|
54 |
-
|
|
|
|
|
|
|
55 |
self._detector = get_detector(config)
|
56 |
self._alerter = get_alerter(config, secrets["gemini_api_key"])
|
57 |
|
@@ -61,24 +62,24 @@ class VideoProcessor(VideoProcessorBase):
|
|
61 |
strategy = config.get('detection_strategy')
|
62 |
if strategy == 'hybrid':
|
63 |
processed_frame, alert_triggered, active_alerts = self._detector.process_frame(img)
|
64 |
-
|
65 |
-
|
|
|
66 |
processed_frame, indicators = self._detector.process_frame(img)
|
67 |
-
alert_triggered = any(indicators.
|
68 |
-
|
69 |
|
70 |
if alert_triggered:
|
71 |
audio_data = self._alerter.trigger_alert()
|
72 |
if audio_data:
|
73 |
-
|
|
|
74 |
else:
|
75 |
self._alerter.reset_alert()
|
76 |
|
77 |
return av.VideoFrame.from_ndarray(processed_frame, format="bgr24")
|
78 |
|
79 |
# --- Page UI ---
|
80 |
-
# The st.set_page_config() call has been removed from this file.
|
81 |
-
# The configuration from main.py will apply to this page.
|
82 |
st.title("📹 Live Drowsiness Detection")
|
83 |
st.info("Press 'START' to activate your camera and begin monitoring.")
|
84 |
|
@@ -87,16 +88,8 @@ ice_servers = [{'urls': 'stun:global.stun.twilio.com:3478'}]
|
|
87 |
if secrets["turn_username"] and secrets["turn_credential"]:
|
88 |
print("TURN credentials found, adding TURN servers to config.")
|
89 |
turn_servers = [
|
90 |
-
{
|
91 |
-
|
92 |
-
'username': secrets["turn_username"],
|
93 |
-
'credential': secrets["turn_credential"]
|
94 |
-
},
|
95 |
-
{
|
96 |
-
'urls': 'turn:global.turn.twilio.com:3478?transport=tcp',
|
97 |
-
'username': secrets["turn_username"],
|
98 |
-
'credential': secrets["turn_credential"]
|
99 |
-
}
|
100 |
]
|
101 |
ice_servers.extend(turn_servers)
|
102 |
|
@@ -108,8 +101,12 @@ col1, col2 = st.columns([3, 1])
|
|
108 |
with col1:
|
109 |
webrtc_ctx = webrtc_streamer(
|
110 |
key="drowsiness-detection",
|
111 |
-
|
112 |
-
|
|
|
|
|
|
|
|
|
113 |
media_stream_constraints={"video": True, "audio": False},
|
114 |
async_processing=True,
|
115 |
)
|
@@ -126,25 +123,18 @@ with col2:
|
|
126 |
audio_placeholder = st.empty()
|
127 |
|
128 |
if webrtc_ctx.state.playing:
|
129 |
-
|
|
|
|
|
130 |
try:
|
|
|
131 |
status_result = st.session_state.status_queue.get(timeout=0.1)
|
|
|
132 |
except queue.Empty:
|
133 |
-
|
134 |
|
135 |
-
# Check for new audio alerts
|
136 |
-
try:
|
137 |
-
audio_data = st.session_state.audio_queue.get(timeout=0.1)
|
138 |
-
except queue.Empty:
|
139 |
-
audio_data = None
|
140 |
-
|
141 |
with status_placeholder.container():
|
142 |
-
|
143 |
-
if status_result:
|
144 |
-
st.session_state.last_status = status_result
|
145 |
-
|
146 |
-
last_status = getattr(st.session_state, 'last_status', {"status": "Awake"})
|
147 |
-
|
148 |
if last_status.get("Low Light"):
|
149 |
st.warning("⚠️ Low Light Detected! Accuracy may be affected.")
|
150 |
elif last_status.get("status") == "Awake":
|
@@ -152,17 +142,18 @@ if webrtc_ctx.state.playing:
|
|
152 |
else:
|
153 |
st.error("🚨 DROWSINESS DETECTED!")
|
154 |
for key, value in last_status.items():
|
155 |
-
if key != "Low Light":
|
156 |
st.warning(f"-> {key}: {value:.2f}" if isinstance(value, float) else f"-> {key}")
|
157 |
|
158 |
-
|
|
|
159 |
with audio_placeholder.container():
|
160 |
autoplay_audio(audio_data)
|
161 |
-
|
162 |
-
|
|
|
163 |
time.sleep(0.1)
|
164 |
st.rerun()
|
165 |
-
|
166 |
else:
|
167 |
with status_placeholder.container():
|
168 |
st.info("✔️ Driver is Awake")
|
|
|
17 |
def load_app_config():
|
18 |
"""Loads config from yaml and .env files."""
|
19 |
load_dotenv()
|
|
|
|
|
20 |
config_path = "/config.yaml" if os.path.exists("/config.yaml") else "config.yaml"
|
21 |
with open(config_path, 'r') as f:
|
22 |
config = yaml.safe_load(f)
|
|
|
30 |
|
31 |
config, secrets = load_app_config()
|
32 |
|
33 |
+
# --- Initialize Session State for Queues at the TOP of the script ---
|
34 |
+
if "status_queue" not in st.session_state:
|
35 |
+
st.session_state.status_queue = queue.Queue()
|
36 |
+
if "audio_queue" not in st.session_state:
|
37 |
+
st.session_state.audio_queue = queue.Queue()
|
38 |
|
39 |
# --- Client-Side Audio Playback Function ---
|
40 |
def autoplay_audio(audio_bytes: bytes):
|
|
|
49 |
|
50 |
# --- WebRTC Video Processor ---
|
51 |
class VideoProcessor(VideoProcessorBase):
|
52 |
+
# The __init__ method now accepts the queues as arguments
|
53 |
+
def __init__(self, status_queue: queue.Queue, audio_queue: queue.Queue):
|
54 |
+
self.status_queue = status_queue
|
55 |
+
self.audio_queue = audio_queue
|
56 |
self._detector = get_detector(config)
|
57 |
self._alerter = get_alerter(config, secrets["gemini_api_key"])
|
58 |
|
|
|
62 |
strategy = config.get('detection_strategy')
|
63 |
if strategy == 'hybrid':
|
64 |
processed_frame, alert_triggered, active_alerts = self._detector.process_frame(img)
|
65 |
+
# Use self.status_queue.put() instead of st.session_state
|
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 |
+
# Use self.audio_queue.put()
|
76 |
+
self.audio_queue.put(audio_data)
|
77 |
else:
|
78 |
self._alerter.reset_alert()
|
79 |
|
80 |
return av.VideoFrame.from_ndarray(processed_frame, format="bgr24")
|
81 |
|
82 |
# --- Page UI ---
|
|
|
|
|
83 |
st.title("📹 Live Drowsiness Detection")
|
84 |
st.info("Press 'START' to activate your camera and begin monitoring.")
|
85 |
|
|
|
88 |
if secrets["turn_username"] and secrets["turn_credential"]:
|
89 |
print("TURN credentials found, adding TURN servers to config.")
|
90 |
turn_servers = [
|
91 |
+
{'urls': 'turn:global.turn.twilio.com:3478?transport=udp', 'username': secrets["turn_username"], 'credential': secrets["turn_credential"]},
|
92 |
+
{'urls': 'turn:global.turn.twilio.com:3478?transport=tcp', 'username': secrets["turn_username"], 'credential': secrets["turn_credential"]}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
93 |
]
|
94 |
ice_servers.extend(turn_servers)
|
95 |
|
|
|
101 |
with col1:
|
102 |
webrtc_ctx = webrtc_streamer(
|
103 |
key="drowsiness-detection",
|
104 |
+
# The factory now correctly passes the queues from session_state
|
105 |
+
video_processor_factory=lambda: VideoProcessor(
|
106 |
+
status_queue=st.session_state.status_queue,
|
107 |
+
audio_queue=st.session_state.audio_queue
|
108 |
+
),
|
109 |
+
rtc_configuration=RTC_CONFIGURATION,
|
110 |
media_stream_constraints={"video": True, "audio": False},
|
111 |
async_processing=True,
|
112 |
)
|
|
|
123 |
audio_placeholder = st.empty()
|
124 |
|
125 |
if webrtc_ctx.state.playing:
|
126 |
+
if "last_status" not in st.session_state:
|
127 |
+
st.session_state.last_status = {"status": "Awake"}
|
128 |
+
|
129 |
try:
|
130 |
+
# This line will now work because st.session_state.status_queue was initialized
|
131 |
status_result = st.session_state.status_queue.get(timeout=0.1)
|
132 |
+
st.session_state.last_status = status_result
|
133 |
except queue.Empty:
|
134 |
+
pass
|
135 |
|
|
|
|
|
|
|
|
|
|
|
|
|
136 |
with status_placeholder.container():
|
137 |
+
last_status = st.session_state.last_status
|
|
|
|
|
|
|
|
|
|
|
138 |
if last_status.get("Low Light"):
|
139 |
st.warning("⚠️ Low Light Detected! Accuracy may be affected.")
|
140 |
elif last_status.get("status") == "Awake":
|
|
|
142 |
else:
|
143 |
st.error("🚨 DROWSINESS DETECTED!")
|
144 |
for key, value in last_status.items():
|
145 |
+
if key != "Low Light" and key != "status":
|
146 |
st.warning(f"-> {key}: {value:.2f}" if isinstance(value, float) else f"-> {key}")
|
147 |
|
148 |
+
try:
|
149 |
+
audio_data = st.session_state.audio_queue.get(timeout=0.1)
|
150 |
with audio_placeholder.container():
|
151 |
autoplay_audio(audio_data)
|
152 |
+
except queue.Empty:
|
153 |
+
pass
|
154 |
+
|
155 |
time.sleep(0.1)
|
156 |
st.rerun()
|
|
|
157 |
else:
|
158 |
with status_placeholder.container():
|
159 |
st.info("✔️ Driver is Awake")
|