繁体   English   中英

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

[英]Pyaudio: How to Playback wav file in separate process(multiprocessing)?

我正在编写一个程序,只要麦克风检测到的幅度超过一定水平,它就应该播放 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

当我单独调用 out.actualoutput() 时,如果完全正常,并且如果我使用多处理与 run() 而不是 start() 它也可以工作。 但是我不能使用 run() 因为我希望主线程继续并且我想使用上面代码中举例说明的 terminate() 选项。 在实际程序中,我显然想在振幅低于阈值时立即调用 terminate() ,而不是在固定的秒数之后。

有没有人知道如何进行这项工作。 即使只是对解决方案的提示也会非常感激。 你好

如果您只想与主程序分开播放文件,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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM