You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flask部署中实现后台播放音频不阻塞OpenCV循环的方法

解决Flask中播放音频阻塞OpenCV视频流的问题

问题根源是playsound属于同步阻塞调用,执行时会卡住视频处理的主线程,导致画面卡顿。下面用你提到的threading和asyncio两种方案解决,直接替换现有代码即可。


方法1:使用threading(最简单直接,适配同步Flask)

把音频播放逻辑放到后台线程中执行,主线程继续处理视频流,完全不会阻塞。

修改后的代码

import threading
from playsound import playsound  # 确保已导入该库

# ... 你的其他初始化代码(比如加载模型、视频流) ...

while True:
    ret, frame = self.video.read()
    results = self.model.track(frame)
    frame_result = results[0].plot()

    for r in results:
        boxes = r.boxes
        for box in boxes:
            c = box.cls
            if model.names[int(c)] == 'cell phone':
                # 启动后台线程播放音频,daemon=True确保线程随主线程退出
                threading.Thread(target=playsound, args=('audio.mp3',), daemon=True).start()
    
    ret, jpeg = cv2.imencode('.jpg', frame_result)
    frame = jpeg.tobytes()
    yield (b'--frame\r\n'
           b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n')

可选优化:避免重复触发

如果短时间内多次检测到手机,会重复启动播放线程导致音频重叠。可以加个标志位控制:

import threading
from playsound import playsound

is_playing = False

def play_alert():
    global is_playing
    if not is_playing:
        is_playing = True
        playsound('audio.mp3')
        is_playing = False

# ... 循环内的判断逻辑 ...
if model.names[int(c)] == 'cell phone':
    threading.Thread(target=play_alert, daemon=True).start()

方法2:使用asyncio(适配异步Flask场景)

如果你的Flask应用用了2.0+的异步路由(async def定义的路由),可以用asyncio结合线程池执行同步的playsound:

修改后的代码

import asyncio
from playsound import playsound

# ... 异步路由内的视频循环逻辑 ...

while True:
    ret, frame = self.video.read()
    results = self.model.track(frame)
    frame_result = results[0].plot()

    for r in results:
        boxes = r.boxes
        for box in boxes:
            c = box.cls
            if model.names[int(c)] == 'cell phone':
                # 用线程池异步执行同步播放函数
                await asyncio.get_event_loop().run_in_executor(None, playsound, 'audio.mp3')
    
    ret, jpeg = cv2.imencode('.jpg', frame_result)
    frame = jpeg.tobytes()
    yield (b'--frame\r\n'
           b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n')

注意:此方案要求你的Flask路由必须是异步定义的(即async def your_route():),否则无法使用await关键字。


内容的提问来源于stack exchange,提问作者dirb

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 11:21:04