Python背景音:如何检测winsound异步播放何时停止
检测winsound异步播放完成并设置flag
嘿,我来帮你搞定这个问题!winsound的异步播放(用SND_ASYNC参数)本身确实没提供直接的回调机制来通知播放结束,但咱们有两种靠谱的办法实现你的需求:
方法一:多线程同步播放+线程内更新flag
这个思路很简单:把同步播放的逻辑放到子线程里,当子线程里的播放任务彻底结束时,就把flag设为1。主线程可以继续跑自己的任务,完全不被阻塞,同时flag会在播放完成时自动更新。
示例代码如下:
import winsound import threading import time flag = 0 def play_audio_and_update_flag(audio_path): global flag # 用同步模式播放(不加SND_ASYNC),播放结束才会执行下一行代码 winsound.PlaySound(audio_path, winsound.SND_FILENAME) flag = 1 print("播放结束,flag已设为1") # 启动子线程执行播放任务 threading.Thread(target=play_audio_and_update_flag, args=("your_audio_file.wav",)).start() # 主线程可以继续做其他事情,这里只是示例轮询flag状态 while flag == 0: print("音频正在播放中...") time.sleep(0.5) print("检测到播放完成!")
小提醒:winsound只支持WAV格式的音频文件,如果你的文件是MP3之类的,得用第二种方法~
方法二:调用Windows原生MCI接口(支持多格式+回调通知)
如果需要更专业的播放完成通知,咱们可以直接调用Windows的winmm.dll里的MCI接口,它支持设置回调函数,当播放彻底结束时,系统会主动触发回调,咱们在回调里更新flag就行。这种方法还支持MP3、WMA等更多音频格式(只要系统装了对应的解码器)。
示例代码:
import ctypes import ctypes.wintypes import time # 加载所需的Windows动态链接库 user32 = ctypes.WinDLL('user32', use_last_error=True) winmm = ctypes.WinDLL('winmm', use_last_error=True) # 定义回调函数的类型 MMRESULT = ctypes.wintypes.DWORD MCI_NOTIFY_CALLBACK = ctypes.WINFUNCTYPE(MMRESULT, ctypes.wintypes.HWND, ctypes.wintypes.UINT, ctypes.wintypes.DWORD, ctypes.wintypes.DWORD) flag = 0 # 播放完成时触发的回调函数 def on_playback_finished(hwnd, msg, wparam, lparam): global flag # MCI_NOTIFY_SUCCESSFUL的消息码是0x03B9 if msg == 0x03B9: flag = 1 print("播放完成!回调已触发flag更新") return 0 # 注册回调函数 callback = MCI_NOTIFY_CALLBACK(on_playback_finished) # 打开音频文件,给它起个别名方便后续操作 audio_path = r"C:\your_path\audio_file.mp3" # 用原始字符串避免转义问题 winmm.mciSendStringW( f'open "{audio_path}" type mpegvideo alias my_audio'.encode('utf-16'), None, 0, None ) # 开始播放,并设置播放完成时通知回调 winmm.mciSendStringW( b"play my_audio notify", None, 0, ctypes.cast(callback, ctypes.wintypes.DWORD) ) # 主线程继续执行其他任务,这里示例等待flag变化 while flag == 0: print("等待播放结束...") time.sleep(0.5) # 播放完成后记得关闭设备,释放资源 winmm.mciSendStringW(b"close my_audio", None, 0, None)
一些注意点
- 多线程方法里,
flag的赋值和读取在Python中是原子操作,所以不用额外加锁,简单场景下完全没问题。 - MCI方法里,音频路径要注意转义,用原始字符串
r""会更省心;如果是WAV文件,把type mpegvideo改成type waveaudio就行。
内容的提问来源于stack exchange,提问作者Diana Laura
相关产品推荐
相关产品推荐

