Add runner wrapper for simple use in Python programs
This commit is contained in:
parent
cb31c79e86
commit
5a1fe8c078
1
runner/precise_runner/__init__.py
Normal file
1
runner/precise_runner/__init__.py
Normal file
@ -0,0 +1 @@
|
|||||||
|
from .runner import PreciseRunner
|
82
runner/precise_runner/runner.py
Normal file
82
runner/precise_runner/runner.py
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
# Python 2 + 3
|
||||||
|
# Copyright (c) 2017 Mycroft AI Inc.
|
||||||
|
|
||||||
|
import atexit
|
||||||
|
from psutil import Popen
|
||||||
|
from subprocess import PIPE
|
||||||
|
from threading import Thread
|
||||||
|
|
||||||
|
|
||||||
|
class PreciseRunner:
|
||||||
|
"""
|
||||||
|
Wrapper to use Precise
|
||||||
|
|
||||||
|
Args:
|
||||||
|
exe_file (str): Location to precise-stream executable
|
||||||
|
model (str): Location to .pb model file to use (with .pb.params)
|
||||||
|
chunk_size (int): Number of samples per prediction. Higher numbers
|
||||||
|
decrease CPU usage but increase latency
|
||||||
|
stream (BinaryIO): Binary audio stream to read 16000 Hz 1 channel int16
|
||||||
|
audio from. If not given, the microphone is used
|
||||||
|
on_prediction: callback for every new prediction
|
||||||
|
on_activation: callback for when the wake word is heard
|
||||||
|
"""
|
||||||
|
def __init__(self, exe_file, model, chunk_size=1024, stream=None,
|
||||||
|
on_prediction=lambda x: None, on_activation=lambda: None):
|
||||||
|
self.pa = None
|
||||||
|
self.stream = stream
|
||||||
|
self.exe_file = exe_file
|
||||||
|
self.model = model
|
||||||
|
self.chunk_size = chunk_size
|
||||||
|
self.thread = None
|
||||||
|
self.proc = None
|
||||||
|
self.on_prediction = on_prediction
|
||||||
|
self.on_activation = on_activation
|
||||||
|
self.running = False
|
||||||
|
self.cooldown = 0
|
||||||
|
atexit.register(self.stop)
|
||||||
|
|
||||||
|
def start(self):
|
||||||
|
"""Start listening from stream"""
|
||||||
|
if self.stream is None:
|
||||||
|
from pyaudio import PyAudio, paInt16
|
||||||
|
self.pa = PyAudio()
|
||||||
|
self.stream = self.pa.open(16000, 1, paInt16, True, frames_per_buffer=self.chunk_size)
|
||||||
|
|
||||||
|
self.proc = Popen([self.exe_file, self.model, str(self.chunk_size)], stdin=PIPE, stdout=PIPE)
|
||||||
|
self.running = True
|
||||||
|
self.thread = Thread(target=self._check_output)
|
||||||
|
self.thread.daemon = True
|
||||||
|
self.thread.start()
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
"""Stop listening and close stream"""
|
||||||
|
if self.thread:
|
||||||
|
self.running = False
|
||||||
|
self.thread.join()
|
||||||
|
self.thread = None
|
||||||
|
|
||||||
|
if self.proc:
|
||||||
|
self.proc.kill()
|
||||||
|
self.proc = None
|
||||||
|
|
||||||
|
if self.pa:
|
||||||
|
self.pa.terminate()
|
||||||
|
self.stream.stop_stream()
|
||||||
|
self.stream = self.pa = None
|
||||||
|
|
||||||
|
def _check_output(self):
|
||||||
|
"""Continuously check Precise process output"""
|
||||||
|
while self.running:
|
||||||
|
chunk = self.stream.read(self.chunk_size)
|
||||||
|
self.proc.stdin.write(chunk)
|
||||||
|
self.proc.stdin.flush()
|
||||||
|
|
||||||
|
prob = float(self.proc.stdout.readline())
|
||||||
|
self.on_prediction(prob)
|
||||||
|
|
||||||
|
if self.cooldown > 0:
|
||||||
|
self.cooldown -= 1
|
||||||
|
elif prob > 0.5:
|
||||||
|
self.cooldown = self.chunk_size // 50
|
||||||
|
self.on_activation()
|
36
runner/setup.py
Executable file
36
runner/setup.py
Executable file
@ -0,0 +1,36 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
from setuptools import setup, find_packages
|
||||||
|
|
||||||
|
setup(
|
||||||
|
name='precise-runner',
|
||||||
|
version='0.1.0',
|
||||||
|
packages=find_packages(),
|
||||||
|
install_requires=[
|
||||||
|
'pyaudio'
|
||||||
|
],
|
||||||
|
|
||||||
|
author='Matthew Scholefield',
|
||||||
|
author_email='matthew.scholefield@mycroft.ai',
|
||||||
|
description='Wrapper to use Mycroft Precise Wake Word Listener',
|
||||||
|
keywords='wakeword keyword wake word listener sound',
|
||||||
|
url='http://github.com/MycroftAI/mycroft-precise',
|
||||||
|
|
||||||
|
zip_safe=True,
|
||||||
|
classifiers=[
|
||||||
|
'Development Status :: 3 - Alpha',
|
||||||
|
'Intended Audience :: Developers',
|
||||||
|
'Topic :: Text Processing :: Linguistic',
|
||||||
|
|
||||||
|
'Programming Language :: Python :: 2',
|
||||||
|
'Programming Language :: Python :: 2.7',
|
||||||
|
'Programming Language :: Python :: 3',
|
||||||
|
'Programming Language :: Python :: 3.0',
|
||||||
|
'Programming Language :: Python :: 3.1',
|
||||||
|
'Programming Language :: Python :: 3.2',
|
||||||
|
'Programming Language :: Python :: 3.3',
|
||||||
|
'Programming Language :: Python :: 3.4',
|
||||||
|
'Programming Language :: Python :: 3.5',
|
||||||
|
'Programming Language :: Python :: 3.6',
|
||||||
|
],
|
||||||
|
)
|
Loading…
x
Reference in New Issue
Block a user