具体来说,我需要在while循环中播放声音,这样执行起来很快。音频需要单独播放。我尝试过各种函数/库:playsound、winsound、vlc。但没有一个能满足我的要求。
要么声音重叠,要么我需要等待声音结束才能继续下一行代码,这阻碍了整个过程,使程序以难以忍受的滞后运行。
playsound、winsound、vlc:中的事项
-
播放声音:有阻止选项,但会阻止进程(使用
block=True
(或重叠声音(block=False
(。 -
winsound:使用
SND_ASYNC
选项,比如我有音频A和音频B(需要在音频A之后播放(,如果播放了音频B,音频A会立即停止。 -
vlc:[0000001ba245794d0]mmdevice音频输出错误:无法初始化COM(错误0x80010106(,这有点奇怪,在谷歌上没有发现任何有用的东西。这种方法对我和其他人来说似乎不是一个好的选择。我只将其用于
is_playing()
函数,就可以将下一个声音放入队列。
有什么建议吗?
如果你刚刚播放完一个声音,并让它中断之前播放的内容,winsound
就会这样做:
import winsound
from time import sleep
winsound.PlaySound("sound.wav", winsound.SND_ASYNC | winsound.SND_FILENAME)
sleep(1)
winsound.PlaySound("sound.wav", winsound.SND_ASYNC | winsound.SND_FILENAME)
sleep(3)
在这个例子中(假设sound.wav
比一秒长(,声音将开始播放,在1秒后被中断,然后再次开始播放。第二个sleep
是为了避免脚本在声音停止之前结束(停止脚本会停止声音(。
如果你想在代码继续运行的同时,将声音一个接一个地排队播放:
import threading
import queue
import winsound
from time import sleep
q = queue.Queue()
def thread_function():
while True:
sound = q.get()
if sound is None:
break
winsound.PlaySound(sound, winsound.SND_FILENAME)
if __name__ == "__main__":
t = threading.Thread(target=thread_function)
t.start()
q.put("sound.wav")
print('One...')
sleep(1)
q.put("sound.wav")
print('Two...')
sleep(1)
q.put("sound.wav")
print('Three...')
q.put(None)
t.join()
这个简单的例子将线程开始播放的声音排队,然后在播放的同时,将下一个声音和稍晚的第三个声音排队。您会注意到,声音一个接一个地播放,程序只有在声音播放完毕时才会停止(线程由于队列末尾的None
而停止(。
如果你想把一个声音放在另一个声音上并让它们混合,使用winsound
是行不通的,但你可以使用像pyglet
这样的库。
例如:
import pyglet
window = pyglet.window.Window()
effect = pyglet.resource.media('sound.wav', streaming=False)
@window.event
def on_key_press(symbol, modifiers):
effect.play()
@window.event
def on_draw():
window.clear()
if __name__ == "__main__":
pyglet.app.run()
本例打开一个窗口,每次按下某个键,它都会立即播放声音,而不会中断以前的声音。关闭窗口后,程序立即结束。
这可以用playsound轻松完成。
playsound.playsound('alert.mp3', False)
将第二个参数设置为False
会使函数异步运行。