停止Winsound / 停止Python中的线程
我正在用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
你的代码有两个主要问题:
- 全局变量
flag_play
需要放在声音播放的循环里,也就是在PlayThis()
函数里面。 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()
如果你需要更多的帮助,请告诉我。