I am creating a personal assistant in Python. I am using Snowboy to record audio, and it works very well. Snowboy has a saveMessage() method that creates and writes a wav file to the disk. This wav file is later read and used as an AudioFile object by Speech_Recognition. I find it very inefficient that the program has to write and read wav files to the disk. I would much rather have the wav file be passed around as an object without EVER saving it to the disk.
Here is the snowboy saveMessage() module that I would like to reweite.
def saveMessage(self):
"""
Save the message stored in self.recordedData to a timestamped file.
"""
filename = 'output' + str(int(time.time())) + '.wav'
data = b''.join(self.recordedData)
#use wave to save data
wf = wave.open(filename, 'wb')
wf.setnchannels(1)
wf.setsampwidth(self.audio.get_sample_size(
self.audio.get_format_from_width(
self.detector.BitsPerSample() / 8)))
wf.setframerate(self.detector.SampleRate())
wf.writeframes(data)
wf.close()
logger.debug("finished saving: " + filename)
return filename #INSTEAD OF RETURNING filename I WANT THIS TO RETURN THE wav file object
Please note that the AudioFile class requires that the path for the wave file OR a "file-like" object must be passed into it. I am not sure what a "file-like" object is, so I will provide the AudioFile assert statement for the wav file argument:
assert isinstance(filename_or_fileobject, (type(""), type(u""))) or hasattr(filename_or_fileobject, "read"), "Given audio file must be a filename string or a file-like object"
I have tried to use an instance of BytesIO to save the wav data, BytesIO is apparently not a file-like object. Here was what I tried:
def saveMessage(self):
filename = 'output' + str(int(time.time())) + '.wav'
data = b''.join(self.recordedData)
#use wave to save data
with io.BytesIO() as wav_file:
wav_writer = wave.open(wav_file, "wb")
try:
wav_writer.setnchannels(1)
wav_writer.setsampwidth(self.audio.get_sample_size(
self.audio.get_format_from_width(
self.detector.BitsPerSample() / 8)))
wav_writer.setframerate(self.detector.SampleRate())
wav_writer.writeframes(data)
wav_data = wav_file.getvalue()
finally:
wav_writer.close()
logger.debug("finished saving: " + filename)
return wav_data
The error I got was: AssertionError: Given audio file must be a filename string or a file-like object
I am using python 3.7 on a Raspberry PI 3B+ running Raspbian Buster Lite kernel version 4.19.36.
If I can provide any additional information or clarify anything, please ask.
Thanks so much!
Something like this should work:
from speech_recognition import AudioData
def saveMessage(self):
filename = 'output' + str(int(time.time())) + '.wav'
data = b''.join(self.recordedData)
ad = AudioData(data, 16000, 2)
result = recognizer.recognize_google(ad)
Note that speech_recognition.listen can invoke snowboy internally, so you probably don't have to use external snowboy, you can just use listen with parameter snowboy_configuration.