停止Winsound / 停止Python中的线程

2 投票
3 回答
3645 浏览
提问于 2025-04-18 02:46

我正在用Python和Tkinter写一个小游戏(顺便说一下,我不能使用任何其他非内置模块),我想在主窗口中播放一首背景音乐,这个窗口里有标题和一些按钮,可以用来切换到其他窗口等等……

问题是,当我进入另一个窗口时,我需要这首音乐停止,但当我点击按钮去另一个窗口时,音乐却一直在播放……

我正在使用winsound模块,并且定义了几个函数(顺便说一下,这些函数非常厉害),用线程在程序启动时播放这首歌……

所以我的想法是,我想在“killsound”这个函数里加点东西,这样我可以把它放到每个按钮上,当我按下任何按钮打开其他窗口时,音乐就会停止。

我希望能有类似'a.kill()'或'a.stop()'这样的东西,但它没有效果。

而且我真的不知道怎么在winsound中使用SND_PURGE这个东西……虽然我知道SND_PURGE在新的Windows操作系统上不再有效(我用的是Win8.1)。

你能帮我一下吗?

谢谢!(抱歉我的英语有点奇怪……)

def Play(nombre): #This function Is the core of the winsound function
   ruta = os.path.join('Audio',nombre)
   Reproducir= winsound.PlaySound(ruta,winsound.SND_FILENAME)
   return Reproducir

def PlayThis(): 
   while flag_play:
       try:
           return Play('prettiest weed.wav')
       except:
           return "Error"

def PlayThisThread():
   global flag_play
   flag_play= True
   a=Thread(target=PlayThis, args=())
   a.daemon = True
   a.start()

   PlayThisThread()


def killsound():  #This is the function I want, for killing sound.
   global flag_play
   flag_play = False

3 个回答

-1

我找到了一种方法,就是给按钮加上一个0.5秒的声音。这样当我按下这个按钮时,它会停止背景音乐,然后播放按钮的声音,最后再停止程序里的所有声音。

0

我在Adobe Audition里做了一个0.5秒的wav文件,这个文件里面是静音的,然后把它连接到了停止按钮上。这样一来,按下停止按钮就基本上“停止”了之前播放的音频片段。

3

你的代码有两个主要问题:

  1. 全局变量 flag_play 需要放在声音播放的循环里,也就是在 PlayThis() 函数里面。
  2. Winsound 模块是为了简单的非线程使用而设计的。在声音播放的时候,无法“温和地”中断它。它不支持任何播放状态的报告,比如 .isPlaying(),也没有 .stop() 这样的功能来停止播放。

解决方案:

  • 可以试试 PyMedia 这个包。Pymedia 允许更底层的音频操作,因此在初始化时需要提供更多的细节:

    import time, wave, pymedia.audio.sound as sound
    
    # little to do on the proper audio setup
    
    f= wave.open( 'prettiest weed.wav', 'rb' )
    sampleRate= f.getframerate() # reads framerate from the file
    channels= f.getnchannels()
    format= sound.AFMT_S16_LE  # this sets the audio format to most common WAV with 16-bit codec PCM Linear Little Endian, use either pymedia or any external utils such as FFMPEG to check / corvert audio into a proper format.
    audioBuffer = 300000  # you are able to control how much audio data is read
    

通过以下赋值,"snd" 变成了 sound.Output 类的一个实例,并且提供了一堆有用的音频方法:

    snd= sound.Output( sampleRate, channels, format )
    s= f.readframes( audioBuffer )
    snd.play( s )

最后,你的线程播放循环可能看起来像这样:

    while snd.isPlaying():
      global flag_play
      if not flag_play: snd.stop()  #here is where the playback gets interupted.
      time.sleep( 0.05 )

    f.close()

如果你需要更多的帮助,请告诉我。

撰写回答