如何在Streamlit项目中实现眼动检测触发的MP3启停控制
解决方案:Streamlit眼部检测联动音频播放
问题根源
st.audio 组件是静态渲染的,无法实时响应视频流中眼部检测状态的动态变化,必须通过前端JS结合Streamlit状态管理来实现播放/暂停的逻辑。
可行实现方案
核心思路:用Streamlit session_state 跟踪眼部检测状态,通过自定义HTML5音频元素+JavaScript来实时控制播放行为,替代原生st.audio。
修改后的完整代码:
import streamlit as st import streamlit_webrtc as webrtc import cv2 def data_page(): st.header("Focus Page") # 初始化状态变量,跟踪眼睛检测状态 if "eye_detected" not in st.session_state: st.session_state.eye_detected = True class VideoTransformer(webrtc.VideoTransformerBase): def __init__(self): self.eye_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_eye.xml') self.current_eye_state = True # 默认检测到眼睛 def transform(self, frame): img = frame.to_ndarray(format="bgr24") gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) eyes = self.eye_cascade.detectMultiScale(gray, scaleFactor=1.3, minNeighbors=5) # 更新检测状态 self.current_eye_state = len(eyes) > 0 if not self.current_eye_state: cv2.putText(img, "No eyes detected", (50, 50), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 255), 2, cv2.LINE_4) else: for (x, y, w, h) in eyes: cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2) return img webrtc_ctx = webrtc.webrtc_streamer( key="example", mode=webrtc.WebRtcMode.SENDRECV, video_transformer_factory=VideoTransformer ) # 实时同步检测状态到session_state if webrtc_ctx.state.playing: st.session_state.eye_detected = webrtc_ctx.video_transformer.current_eye_state # 自定义音频控件+JS控制逻辑 # 替换为你的本地MP3文件路径,建议放在与脚本同目录下 mp3_file_path = "alert.mp3" # 读取音频文件为base64(避免跨路径问题) import base64 with open(mp3_file_path, "rb") as f: audio_bytes = f.read() audio_base64 = base64.b64encode(audio_bytes).decode() # 渲染HTML音频元素和控制脚本 st.markdown(f""" <audio id="alert-audio" controls loop style="display:none"> <source src="data:audio/mp3;base64,{audio_base64}" type="audio/mp3"> </audio> <script> const audio = document.getElementById('alert-audio'); // 监听Streamlit状态变化 function checkEyeState() {{ const eyeDetected = {st.session_state.eye_detected}; if (!eyeDetected && audio.paused) {{ audio.play(); }} else if (eyeDetected && !audio.paused) {{ audio.pause(); audio.currentTime = 0; // 重置到开头 }} }} // 定时检查状态,间隔500ms setInterval(checkEyeState, 500); </script> """, unsafe_allow_html=True) if __name__ == "__main__": data_page()
关键细节说明
- 状态同步:通过
webrtc_ctx.video_transformer.current_eye_state获取实时检测结果,同步到session_state中 - 音频处理:将本地MP3转为Base64嵌入HTML,避免文件路径访问问题;隐藏原生控件,通过JS自动控制
- 播放逻辑:JS定时检查状态,未检测到眼睛时自动播放,检测到后暂停并重置音频
- 性能优化:500ms的检查间隔平衡了实时性和前端性能
内容的提问来源于stack exchange,提问作者Umar
相关产品推荐
相关产品推荐

