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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 09:14:13