如何解决Pyaudio:如何在单独的进程多处理中播放wav文件?
我正在编写一个程序,只要麦克风检测到的振幅超过一定水平,就应该播放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的import cv2
import numpy as np
def convert_to_binary(rgb_image):
gray_image = cv2.cvtColor(rgb_image,cv2.COLOR_BGR2GRAY)
ret,thresh = cv2.threshold(gray_image,180,255,cv2.THRESH_BINARY_INV)
return gray_image,thresh
original = cv2.imread('original.jpg')
height,width = original.shape[:2]
original_gray,original_binary = convert_to_binary(original) # Get binary image
cv2.imwrite("binary.jpg",original_binary)
closing_original = cv2.morphologyEx(original_binary,cv2.MORPH_DILATE,np.ones((1,2),np.uint8)) # Close small gaps in the binary image
cv2.imwrite("closed.jpg",closing_original)
contours_original,hierarchy_original = cv2.findContours(closing_original,cv2.RETR_CCOMP,cv2.CHAIN_APPROX_SIMPLE) # Get all the contours
bounding_rects_original = [cv2.boundingRect(c) for c in contours_original] # Get all contour bounding boxes
orig_boxes = list()
all_contour_image = original.copy()
for i,(x,y,w,h) in enumerate(bounding_rects_original):
if h > height / 2 or w > width / 2: # Eliminate extremely large contours
continue
if h < w / 2 or w < h / 2: # Eliminate vertical / horuzontal lines
continue
if w * h < 200: # Eliminate small area contours
continue
if hierarchy_original[0][i][3] != -1: # Eliminate contours created by heart crosses
continue
orig_boxes.append((x,h))
cv2.rectangle(all_contour_image,y),(x + w,y + h),(0,0),3)
# cv2.imshow("warped",closing_original)
cv2.imwrite("all_contours.jpg",all_contour_image)
final_image = original.copy()
for x,h in orig_boxes:
cropped_image = closing_original[y - 2 :y + h + 2,x: x + w] # Get the heart binary image
col_pixel_diffs = np.abs(np.diff(cropped_image.T.astype(np.int16))/255) # Obtain all consecutive pixel differences in all the columns
column_sums = np.sum(col_pixel_diffs,axis=1) # Get the sum of each column's transitions. This results in an array of size equal
# to the number of columns,each element representing the number of black-white and white-black transitions.
percent_crosses = np.sum(column_sums >= 6)/ np.sum(column_sums >= 4) # Percentage of columns with 6 transitions among columns with 4 transitions
if percent_crosses > 0.4: # Crossed heart criterion
cv2.rectangle(final_image,3)
cv2.imwrite("crossed_heart.jpg",cropped_image)
else:
cv2.imwrite("normal_heart.jpg",cropped_image)
cv2.imwrite("all_crossed_hearts.jpg",final_image)
可能是最好的选择。当有多个线程并且需要同时启动它们并收集结果时,首选进行多处理。
例如:
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()}')
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。