Hello community,
here is the log from the commit of package python-precise-runner for openSUSE:Factory checked in at 2019-06-06 18:15:49
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-precise-runner (Old)
and /work/SRC/openSUSE:Factory/.python-precise-runner.new.4811 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-precise-runner"
Thu Jun 6 18:15:49 2019 rev:2 rq:707125 version:0.3.1
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-precise-runner/python-precise-runner.changes 2018-07-31 16:00:20.695642714 +0200
+++ /work/SRC/openSUSE:Factory/.python-precise-runner.new.4811/python-precise-runner.changes 2019-06-06 18:15:49.812712244 +0200
@@ -1,0 +2,6 @@
+Mon Jun 3 10:29:36 UTC 2019 - Tomáš Chvátal
+
+- Update to 0.3.1:
+ * Upstream changelog mentions only massive number of improvements
+
+-------------------------------------------------------------------
Old:
----
precise-runner-0.2.1.tar.gz
New:
----
precise-runner-0.3.1.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-precise-runner.spec ++++++
--- /var/tmp/diff_new_pack.XrrFte/_old 2019-06-06 18:15:50.700711985 +0200
+++ /var/tmp/diff_new_pack.XrrFte/_new 2019-06-06 18:15:50.704711983 +0200
@@ -1,7 +1,7 @@
#
# spec file for package python-precise-runner
#
-# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany.
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
@@ -12,20 +12,23 @@
# license that conforms to the Open Source Definition (Version 1.9)
# published by the Open Source Initiative.
-# Please submit bugfixes or comments via http://bugs.opensuse.org/
+# Please submit bugfixes or comments via https://bugs.opensuse.org/
#
%{?!python_module:%define python_module() python-%{**} python3-%{**}}
Name: python-precise-runner
-Version: 0.2.1
+Version: 0.3.1
Release: 0
Summary: Wrapper to use Mycroft Precise Wake Word Listener
License: Apache-2.0
Group: Development/Languages/Python
URL: http://github.com/MycroftAI/mycroft-precise
Source: https://files.pythonhosted.org/packages/source/p/precise-runner/precise-runner-%{version}.tar.gz
+# https://github.com/MycroftAI/mycroft-precise/issues/74
Source99: https://raw.githubusercontent.com/MycroftAI/mycroft-precise/dev/LICENSE
+BuildRequires: %{python_module PyAudio}
+BuildRequires: %{python_module pytest}
BuildRequires: %{python_module setuptools}
BuildRequires: fdupes
BuildRequires: python-rpm-macros
@@ -47,6 +50,9 @@
%python_install
%python_expand %fdupes %{buildroot}%{$python_sitelib}
+%check
+%pytest
+
%files %{python_files}
%doc README.md
%license LICENSE
++++++ precise-runner-0.2.1.tar.gz -> precise-runner-0.3.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/precise-runner-0.2.1/PKG-INFO new/precise-runner-0.3.1/PKG-INFO
--- old/precise-runner-0.2.1/PKG-INFO 2018-06-19 01:43:54.000000000 +0200
+++ new/precise-runner-0.3.1/PKG-INFO 2019-05-15 09:34:33.000000000 +0200
@@ -1,6 +1,6 @@
Metadata-Version: 1.1
Name: precise-runner
-Version: 0.2.1
+Version: 0.3.1
Summary: Wrapper to use Mycroft Precise Wake Word Listener
Home-page: http://github.com/MycroftAI/mycroft-precise
Author: Matthew Scholefield
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/precise-runner-0.2.1/README.md new/precise-runner-0.3.1/README.md
--- old/precise-runner-0.2.1/README.md 2018-04-18 07:12:20.000000000 +0200
+++ new/precise-runner-0.3.1/README.md 2019-05-01 08:04:54.000000000 +0200
@@ -12,7 +12,8 @@
```bash
ARCH=x86_64
-wget https://github.com/MycroftAI/precise-data/raw/dist/$ARCH/precise-engine.tar....
+VERSION=0.3.0
+wget https://github.com/MycroftAI/mycroft-precise/releases/download/$VERSION/precise-all_${VERSION}_${ARCH}.tar.gz
tar xvf precise-engine.tar.gz
```
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/precise-runner-0.2.1/precise_runner/__init__.py new/precise-runner-0.3.1/precise_runner/__init__.py
--- old/precise-runner-0.2.1/precise_runner/__init__.py 2018-06-18 23:16:33.000000000 +0200
+++ new/precise-runner-0.3.1/precise_runner/__init__.py 2019-05-15 09:33:10.000000000 +0200
@@ -1,3 +1,3 @@
from .runner import PreciseRunner, PreciseEngine, ReadWriteStream
-__version__ = '0.2.1'
+__version__ = '0.3.1'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/precise-runner-0.2.1/precise_runner/runner.py new/precise-runner-0.3.1/precise_runner/runner.py
--- old/precise-runner-0.2.1/precise_runner/runner.py 2018-06-12 20:57:40.000000000 +0200
+++ new/precise-runner-0.3.1/precise_runner/runner.py 2019-05-15 09:32:34.000000000 +0200
@@ -1,5 +1,5 @@
# Python 2 + 3
-# Copyright 2018 Mycroft AI Inc.
+# Copyright 2019 Mycroft AI Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -13,6 +13,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import atexit
+
+import time
from subprocess import PIPE, Popen
from threading import Thread, Event
@@ -72,17 +74,31 @@
class ReadWriteStream(object):
- """Class used to support writing binary audio data at any pace"""
- def __init__(self, s=b''):
+ """
+ Class used to support writing binary audio data at any pace,
+ optionally chopping when the buffer gets too large
+ """
+ def __init__(self, s=b'', chop_samples=-1):
self.buffer = s
self.write_event = Event()
+ self.chop_samples = chop_samples
+
+ def __len__(self):
+ return len(self.buffer)
def read(self, n=-1, timeout=None):
if n == -1:
n = len(self.buffer)
+ if 0 < self.chop_samples < len(self.buffer):
+ samples_left = len(self.buffer) % self.chop_samples
+ self.buffer = self.buffer[-samples_left:]
+ return_time = 1e10 if timeout is None else (
+ timeout + time.time()
+ )
while len(self.buffer) < n:
self.write_event.clear()
- self.write_event.wait(timeout)
+ if not self.write_event.wait(return_time - time.time()):
+ return b''
chunk = self.buffer[:n]
self.buffer = self.buffer[n:]
return chunk
@@ -92,6 +108,36 @@
self.write_event.set()
+class TriggerDetector:
+ """
+ Reads predictions and detects activations
+ This prevents multiple close activations from occurring when
+ the predictions look like ...!!!..!!...
+ """
+ def __init__(self, chunk_size, sensitivity=0.5, trigger_level=3):
+ self.chunk_size = chunk_size
+ self.sensitivity = sensitivity
+ self.trigger_level = trigger_level
+ self.activation = 0
+
+ def update(self, prob):
+ # type: (float) -> bool
+ """Returns whether the new prediction caused an activation"""
+ chunk_activated = prob > 1.0 - self.sensitivity
+
+ if chunk_activated or self.activation < 0:
+ self.activation += 1
+ has_activated = self.activation > self.trigger_level
+ if has_activated or chunk_activated and self.activation < 0:
+ self.activation = -(8 * 2048) // self.chunk_size
+
+ if has_activated:
+ return True
+ elif self.activation > 0:
+ self.activation -= 1
+ return False
+
+
class PreciseRunner(object):
"""
Wrapper to use Precise. Example:
@@ -107,8 +153,7 @@
engine (Engine): Object containing info on the binary engine
trigger_level (int): Number of chunk activations needed to trigger on_activation
Higher values add latency but reduce false positives
- sensitivity (float): From 0.0 to 1.0, relates to the network output level required
- to consider a chunk "active"
+ sensitivity (float): From 0.0 to 1.0, how sensitive the network should be
stream (BinaryIO): Binary audio stream to read 16000 Hz 1 channel int16
audio from. If not given, the microphone is used
on_prediction (Callable): callback for every new prediction
@@ -119,31 +164,26 @@
on_prediction=lambda x: None, on_activation=lambda: None):
self.engine = engine
self.trigger_level = trigger_level
- self.sensitivity = sensitivity
self.stream = stream
self.on_prediction = on_prediction
self.on_activation = on_activation
self.chunk_size = engine.chunk_size
- self.read_divisor = 1
self.pa = None
self.thread = None
self.running = False
self.is_paused = False
+ self.detector = TriggerDetector(self.chunk_size, sensitivity, trigger_level)
atexit.register(self.stop)
- def _calc_read_divisor(self):
+ def _wrap_stream_read(self, stream):
"""
pyaudio.Stream.read takes samples as n, not bytes
- so read(n) should be read(n // sample_depth
+ so read(n) should be read(n // sample_depth)
"""
- try:
- import pyaudio
- if isinstance(self.stream, pyaudio.Stream):
- return 2
- except ImportError:
- pass
- return 1
+ import pyaudio
+ if getattr(stream.read, '__func__', None) is pyaudio.Stream.read:
+ stream.read = lambda x: pyaudio.Stream.read(stream, x // 2, False)
def start(self):
"""Start listening from stream"""
@@ -154,12 +194,12 @@
16000, 1, paInt16, True, frames_per_buffer=self.chunk_size
)
- self.read_divisor = self._calc_read_divisor()
+ self._wrap_stream_read(self.stream)
self.engine.start()
self.running = True
self.is_paused = False
- self.thread = Thread(target=self._handle_predictions)
+ self.thread = Thread(target=self._handle_predictions, daemon=True)
self.thread.daemon = True
self.thread.start()
@@ -187,24 +227,13 @@
def _handle_predictions(self):
"""Continuously check Precise process output"""
- activation = 0
while self.running:
- chunk = self.stream.read(self.chunk_size // self.read_divisor)
+ chunk = self.stream.read(self.chunk_size)
if self.is_paused:
continue
prob = self.engine.get_prediction(chunk)
self.on_prediction(prob)
- chunk_activated = prob > 1 - self.sensitivity
-
- if chunk_activated or activation < 0:
- activation += 1
- has_activated = activation > self.trigger_level
- if has_activated:
- self.on_activation()
-
- if has_activated or chunk_activated and activation < 0:
- activation = -(8 * 2048) // self.chunk_size
- elif activation > 0:
- activation -= 1
+ if self.detector.update(prob):
+ self.on_activation()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/precise-runner-0.2.1/precise_runner.egg-info/PKG-INFO new/precise-runner-0.3.1/precise_runner.egg-info/PKG-INFO
--- old/precise-runner-0.2.1/precise_runner.egg-info/PKG-INFO 2018-06-19 01:43:54.000000000 +0200
+++ new/precise-runner-0.3.1/precise_runner.egg-info/PKG-INFO 2019-05-15 09:34:33.000000000 +0200
@@ -1,6 +1,6 @@
Metadata-Version: 1.1
Name: precise-runner
-Version: 0.2.1
+Version: 0.3.1
Summary: Wrapper to use Mycroft Precise Wake Word Listener
Home-page: http://github.com/MycroftAI/mycroft-precise
Author: Matthew Scholefield
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/precise-runner-0.2.1/precise_runner.egg-info/SOURCES.txt new/precise-runner-0.3.1/precise_runner.egg-info/SOURCES.txt
--- old/precise-runner-0.2.1/precise_runner.egg-info/SOURCES.txt 2018-06-19 01:43:54.000000000 +0200
+++ new/precise-runner-0.3.1/precise_runner.egg-info/SOURCES.txt 2019-05-15 09:34:33.000000000 +0200
@@ -2,9 +2,11 @@
setup.py
precise_runner/__init__.py
precise_runner/runner.py
+precise_runner/util.py
precise_runner.egg-info/PKG-INFO
precise_runner.egg-info/SOURCES.txt
precise_runner.egg-info/dependency_links.txt
precise_runner.egg-info/requires.txt
precise_runner.egg-info/top_level.txt
-precise_runner.egg-info/zip-safe
\ No newline at end of file
+precise_runner.egg-info/zip-safe
+test/test_runner.py
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/precise-runner-0.2.1/setup.py new/precise-runner-0.3.1/setup.py
--- old/precise-runner-0.2.1/setup.py 2018-04-18 07:12:20.000000000 +0200
+++ new/precise-runner-0.3.1/setup.py 2019-03-20 16:53:04.000000000 +0100
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright 2018 Mycroft AI Inc.
+# Copyright 2019 Mycroft AI Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/precise-runner-0.2.1/test/test_runner.py new/precise-runner-0.3.1/test/test_runner.py
--- old/precise-runner-0.2.1/test/test_runner.py 1970-01-01 01:00:00.000000000 +0100
+++ new/precise-runner-0.3.1/test/test_runner.py 2019-05-13 18:42:32.000000000 +0200
@@ -0,0 +1,18 @@
+from precise_runner import ReadWriteStream
+
+
+class TestReadWriteStream:
+ def test_read_write(self):
+ s = ReadWriteStream(b'1234567890')
+ assert s.read(2) == b'12'
+ assert s.read(2) == b'34'
+ s.write(b'hi')
+ assert s.read() == b'567890hi'
+ s.write(b'hello')
+ assert s.read() == b'hello'
+ assert s.read(1, timeout=0.1) == b''
+
+ def test_chop(self):
+ s = ReadWriteStream(chop_samples=10)
+ s.write(b'1234567890hello')
+ assert s.read(5) == b'hello'