0

具体来说,我需要在一个快速执行的while循环中播放声音。并且音频需要单独播放。我尝试了各种功能/库:playsound、winsound、vlc。但没有一个能满足我的要求。

要么声音重叠,要么我需要等待声音完成才能继续下一行代码,这会阻塞整个过程,使程序运行时出现无法忍受的延迟。

playsound、winsound、vlc中的问题:

  • playsound:有阻塞选项,但会阻塞进程(用block=True)或重叠声音(block=False)。

  • winsound:有SND_ASYNC选项,假设我有音频A和音频B(需要在音频A之后播放),如果播放音频B,音频A将立即停止。

  • vlc:[000001ba245794d0] mmdevice 音频输出错误:无法初始化 COM(错误 0x80010106),这有点奇怪,在 Google 上找不到任何有用的东西。这种方法对我和其他人来说似乎不是一个好的选择。我只是将它用于它的is_playing()功能,我可以将下一个声音放入队列中。

那么有什么建议吗?

4

2 回答 2

1

如果您刚刚播放声音并让它中断之前播放的任何内容,请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()

这个例子打开一个窗口,每次你按下一个键,它会立即播放声音,不会打断之前的声音。当您关闭窗口时,程序会立即结束。

于 2020-04-14T05:10:03.227 回答
0

这可以通过playsound轻松完成。

playsound.playsound('alert.mp3', False)

将第二个参数设置为False使函数异步运行。

于 2021-05-16T19:36:18.497 回答