Hello,
I’ve been testing Precise as a wake-word engine for my companion robot project (GitHub - ScottMonaghan/robud: Loveable Accessible Autonomous Robot).
If I create a stream object using pyaudio.open, I’m able to specify my input device, pass it into the precise runner in python and it works great!
The problem is, I can’t allow the precise python script to take full control of my audio card because it’s used by several other processes.
The way that I handle this is that I publish the raw input bytestream with the Moquitto MQTT messaging system.
With other tools I’m able to subscribe to that stream and then use it the audio however I wish, but with precise I’ve been having trouble.
I’m able to subscribe and write the stream to a BytesIO object, and I can specify the BytesIO object as the stream when initializing my runner.
But when I start the runner, I get an error stating there are 0 frames.
Can anyone offer any advice on how to achieve this?
Here are the related python snippets:
def on_message_audio_input_data(client:mqtt.Client, userdata, message):
#print("audio recieived")
audio_buffer:BytesIO = userdata["audio_buffer"]
audio_buffer.write(message.payload)
#Create audio buffer
audio_buffer = BytesIO()
client_userdata = {"audio_buffer":audio_buffer}
mqtt_client = mqtt.Client(client_id=MQTT_CLIENT_NAME,userdata=client_userdata)
mqtt_client.connect(MQTT_BROKER_ADDRESS)
logger.info('MQTT Client Connected')
mqtt_client.subscribe(TOPIC_AUDIO_INPUT_DATA)
mqtt_client.message_callback_add(TOPIC_AUDIO_INPUT_DATA, on_message_audio_input_data)
logger.info('Subscribed to ' + TOPIC_AUDIO_INPUT_DATA)
#stream.start_stream()
logger.info('Waiting for messages...')
mqtt_client.loop_start()
#Create audio buffer
#audio_buffer = BytesIO()
engine = PreciseEngine('/home/robud/Downloads/precise-engine/precise-engine', '/home/robud/src/precise-data/hey-mycroft.pb')
runner = PreciseRunner(engine=engine, stream=audio_buffer, on_activation=lambda: print('activated!'))
#runner.start()
# Sleep forever
from time import sleep
while True:
if audio_buffer.getbuffer().nbytes > CHUNK and not(runner.running): #2 bytes for each 16bit frame
logger.info('runner started')
runner.start()
sleep(0.1)