Pyaudio:如何在单独进程(多进程)中播放wav文件?

2024-09-26 18:14:23 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在编写一个程序,只要麦克风检测到的振幅超过一定水平,就应该播放wav文件。我想使用pyaudio(过去在某种程度上已经成功),因为我需要同时处理2个流。现在问题出现在何时

我想在独立于主线程的进程中播放wav文件。以下代码只是概念证明:

import pyaudio,wave
import multiprocessing,time

filename='/home/larfan/Documents/PythonProgramming/overtone_horn/soundsamples/ZOOM0065.WAV'
#open soundfile
wf = wave.open(filename, 'rb')


chunk = 1024*4  
p = pyaudio.PyAudio()
class output:
    def __init__(self):
        self.stream = p.open(format = p.get_format_from_width(wf.getsampwidth()),
                    channels = wf.getnchannels(),
                    rate = wf.getframerate(),
                    output = True)
        # Read data in chunks
        self.origdata = wf.readframes(chunk)
    def actualoutput(self):
        data=self.origdata
        # Play the sound by writing the audio data to the stream
        while data:
            self.stream.write(data)
            data = wf.readframes(chunk)
    def testfuntion(self):
        print('hi')
        

out=output()

t1=multiprocessing.Process(target=out.actualoutput)
t1.start()
time.sleep(2)
out.stream.close()

t1.terminate()


p.terminate()

如果我运行此代码,我会得到:

Traceback (most recent call last):
  File "/usr/lib/python3.7/multiprocessing/process.py", line 297, in _bootstrap
    self.run()
  File "/usr/lib/python3.7/multiprocessing/process.py", line 99, in run
    self._target(*self._args, **self._kwargs)
  File "/home/larfan/Documents/PythonProgramming/overtone_horn/ultimatetest.py", line 23, in actualoutput
    self.stream.write(data)
  File "/usr/lib/python3/dist-packages/pyaudio.py", line 586, in write
    exception_on_underflow)
OSError: [Errno -9999] Unanticipated host error

当我调用.actualoutput()时,如果完全可以工作,并且如果我使用run()而不是start()进行多处理,那么它也可以工作。但是,我不能使用run(),因为我希望主线程继续运行,并且希望使用上面代码中的terminate()选项。在实际程序中,我显然希望在振幅下降到阈值以下时调用terminate(),而不是在固定的秒数之后

有没有人知道如何使这项工作。即使只是对解决方案的一个暗示也将非常感激。 问候


Tags: run代码inpyselfdatastreamline
1条回答
网友
1楼 · 发布于 2024-09-26 18:14:23

如果您只想将文件与主程序分开播放,asyncio的run_in_executor()可能是最好的方式。当有多个线程并且需要同时启动它们并收集结果时,最好使用多处理

例如:

import pyaudio
import wave
import sys
import asyncio
from datetime import datetime
def background(f):
    def wrapped(*args, **kwargs):
        return asyncio.get_event_loop().run_in_executor(None, f, *args, **kwargs)
    return wrapped

@background
def play_audio(audio_file = 'sample.wav', CHUNK = 1024): #define play function however you like!
    print(f'Audio Play starts at {datetime.now()}')
    wf = wave.open(audio_file, 'rb')

    p = pyaudio.PyAudio()

    stream = p.open(format=p.get_format_from_width(wf.getsampwidth()),
                    channels=wf.getnchannels(),
                    rate=wf.getframerate(),
                    output=True)

    data = wf.readframes(CHUNK)

    while len(data)!=0:
        stream.write(data)
        data = wf.readframes(CHUNK)

    stream.stop_stream()
    stream.close()

    p.terminate()
    print(f'Audio play finishes {datetime.now()}')

现在您可以根据需要运行调用此函数,它将始终单独运行到主程序,而不会将其置于等待状态:

print(f'Main Program Starts at {datetime.now()}')
play_audio('sample.wav', 1024)
print(f'Main program finishes at {datetime.now()}')

产生以下输出:

Main Program Starts at 2020-10-24 16:57:30.819964
Audio Play starts at 2020-10-24 16:57:30.819964
Main program finishes at 2020-10-24 16:57:30.820960
Audio play finishes 2020-10-24 16:58:04.684334

相关问题 更多 >

    热门问题