Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v2.0 python #256

Merged
merged 15 commits into from
Nov 23, 2023
4 changes: 2 additions & 2 deletions .github/workflows/python-codestyle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ name: Python Codestyle
on:
workflow_dispatch:
push:
branches: [master]
branches: [ master ]
paths:
- 'binding/python/*.py'
- 'demo/python/*.py'
pull_request:
branches: [master]
branches: [ master, 'v[0-9]+.[0-9]+' ]
paths:
- 'binding/python/*.py'
- 'demo/python/*.py'
Expand Down
16 changes: 14 additions & 2 deletions .github/workflows/python-demos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ name: Python Demos
on:
workflow_dispatch:
push:
branches: [master]
branches: [ master ]
paths:
- '.github/workflows/python-demos.yml'
- 'demo/python/**'
- '!demo/python/README.md'
pull_request:
branches: [master]
branches: [ master, 'v[0-9]+.[0-9]+' ]
paths:
- '.github/workflows/python-demos.yml'
- 'demo/python/**'
Expand Down Expand Up @@ -39,6 +39,12 @@ jobs:
- name: Pre-build dependencies
run: python -m pip install --upgrade pip

# ************** REMOVE AFTER RELEASE ********************
- name: Build binding
run: |
pip install wheel && cd ../../binding/python && python setup.py sdist bdist_wheel && pip install dist/pvcheetah-2.0.0-py3-none-any.whl
# ********************************************************

- name: Install dependencies
run: pip install -r requirements.txt

Expand All @@ -55,6 +61,12 @@ jobs:
steps:
- uses: actions/checkout@v3

# ************** REMOVE AFTER RELEASE ********************
- name: Build binding
run: |
pip3 install wheel && cd ../../binding/python && python3 setup.py sdist bdist_wheel && pip3 install dist/pvcheetah-2.0.0-py3-none-any.whl
# ********************************************************

- name: Install dependencies
run: pip3 install -r requirements.txt

Expand Down
36 changes: 18 additions & 18 deletions .github/workflows/python-perf.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: Python performance
on:
workflow_dispatch:
push:
branches: [master]
branches: [ master ]
paths:
- '.github/workflows/python-perf.yml'
- 'binding/python/test_cheetah_perf.py'
Expand All @@ -14,7 +14,7 @@ on:
- 'lib/raspberry-pi/**'
- 'lib/windows/**'
pull_request:
branches: [master]
branches: [ master, 'v[0-9]+.[0-9]+' ]
paths:
- '.github/workflows/python-perf.yml'
- 'binding/python/test_cheetah_perf.py'
Expand All @@ -39,14 +39,14 @@ jobs:
os: [ubuntu-latest, windows-latest, macos-latest]
include:
- os: ubuntu-latest
init_performance_threshold_sec: 2.1
proc_performance_threshold_sec: 0.5
init_performance_threshold_sec: 4.0
proc_performance_threshold_sec: 0.8
- os: windows-latest
init_performance_threshold_sec: 2.4
proc_performance_threshold_sec: 0.6
init_performance_threshold_sec: 4.0
proc_performance_threshold_sec: 0.7
- os: macos-latest
init_performance_threshold_sec: 3.0
proc_performance_threshold_sec: 0.8
init_performance_threshold_sec: 4.5
proc_performance_threshold_sec: 2.5

steps:
- uses: actions/checkout@v3
Expand Down Expand Up @@ -74,20 +74,20 @@ jobs:
machine: [rpi3-32, rpi3-64, rpi4-32, rpi4-64, jetson]
include:
- machine: rpi3-32
init_performance_threshold_sec: 7.5
proc_performance_threshold_sec: 3.6
init_performance_threshold_sec: 9.0
proc_performance_threshold_sec: 9.0
- machine: rpi3-64
init_performance_threshold_sec: 8.3
proc_performance_threshold_sec: 3.5
init_performance_threshold_sec: 9.0
proc_performance_threshold_sec: 7.5
- machine: rpi4-32
init_performance_threshold_sec: 5.7
proc_performance_threshold_sec: 2.0
init_performance_threshold_sec: 7.5
proc_performance_threshold_sec: 4.0
- machine: rpi4-64
init_performance_threshold_sec: 5.1
proc_performance_threshold_sec: 1.9
init_performance_threshold_sec: 7.5
proc_performance_threshold_sec: 4.0
- machine: jetson
init_performance_threshold_sec: 5.2
proc_performance_threshold_sec: 1.9
init_performance_threshold_sec: 7.5
proc_performance_threshold_sec: 4.0

steps:
- uses: actions/checkout@v3
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/python.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: Python
on:
workflow_dispatch:
push:
branches: [master]
branches: [ master ]
paths:
- '.github/workflows/python.yml'
- 'binding/python/**'
Expand All @@ -15,7 +15,7 @@ on:
- 'lib/raspberry-pi/**'
- 'lib/windows/**'
pull_request:
branches: [master]
branches: [ master, 'v[0-9]+.[0-9]+' ]
paths:
- '.github/workflows/python.yml'
- 'binding/python/**'
Expand Down
81 changes: 73 additions & 8 deletions binding/python/_cheetah.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,27 @@


class CheetahError(Exception):
pass
def __init__(self, message: str = '', message_stack: Sequence[str] = None):
super().__init__(message)

self._message = message
self._message_stack = list() if message_stack is None else message_stack

def __str__(self):
message = self._message
if len(self._message_stack) > 0:
message += ':'
for i in range(len(self._message_stack)):
message += '\n [%d] %s' % (i, self._message_stack[i])
return message

@property
def message(self) -> str:
return self._message

@property
def message_stack(self) -> Sequence[str]:
return self._message_stack


class CheetahMemoryError(CheetahError):
Expand Down Expand Up @@ -122,14 +142,28 @@ def __init__(
if not os.path.exists(library_path):
raise CheetahIOError("Could not find Cheetah's dynamic library at `%s`." % library_path)

library = cdll.LoadLibrary(library_path)

if not os.path.exists(model_path):
raise CheetahIOError("Could not find model file at `%s`." % model_path)

if endpoint_duration_sec is not None and not endpoint_duration_sec > 0.:
raise CheetahInvalidArgumentError("`endpoint_duration_sec` must be either `None` or a positive number")

library = cdll.LoadLibrary(library_path)

set_sdk_func = library.pv_set_sdk
set_sdk_func.argtypes = [c_char_p]
set_sdk_func.restype = None

set_sdk_func('python'.encode('utf-8'))

self._get_error_stack_func = library.pv_get_error_stack
self._get_error_stack_func.argtypes = [POINTER(POINTER(c_char_p)), POINTER(c_int)]
self._get_error_stack_func.restype = self.PicovoiceStatuses

self._free_error_stack_func = library.pv_free_error_stack
self._free_error_stack_func.argtypes = [POINTER(c_char_p)]
self._free_error_stack_func.restype = None

init_func = library.pv_cheetah_init
init_func.argtypes = [c_char_p, c_char_p, c_float, c_bool, POINTER(POINTER(self.CCheetah))]
init_func.restype = self.PicovoiceStatuses
Expand All @@ -143,7 +177,9 @@ def __init__(
enable_automatic_punctuation,
byref(self._handle))
if status is not self.PicovoiceStatuses.SUCCESS:
raise self._PICOVOICE_STATUS_TO_EXCEPTION[status]()
raise self._PICOVOICE_STATUS_TO_EXCEPTION[status](
message='Initialization failed',
message_stack=self._get_error_stack())

self._delete_func = library.pv_cheetah_delete
self._delete_func.argtypes = [POINTER(self.CCheetah)]
Expand All @@ -158,6 +194,10 @@ def __init__(
self._flush_func.argtypes = [POINTER(self.CCheetah), POINTER(c_char_p)]
self._flush_func.restype = self.PicovoiceStatuses

self._transcript_delete_func = library.pv_cheetah_transcript_delete
self._transcript_delete_func.argtypes = [c_char_p]
self._transcript_delete_func.restype = None

version_func = library.pv_cheetah_version
version_func.argtypes = []
version_func.restype = c_char_p
Expand Down Expand Up @@ -192,9 +232,14 @@ def process(self, pcm: Sequence[int]) -> Tuple[str, bool]:
byref(c_partial_transcript),
byref(is_endpoint))
if status is not self.PicovoiceStatuses.SUCCESS:
raise self._PICOVOICE_STATUS_TO_EXCEPTION[status]()
raise self._PICOVOICE_STATUS_TO_EXCEPTION[status](
message='Process failed',
message_stack=self._get_error_stack())

partial_transcript = c_partial_transcript.value.decode('utf-8')
self._transcript_delete_func(c_partial_transcript)

return c_partial_transcript.value.decode('utf-8'), is_endpoint.value
return partial_transcript, is_endpoint.value

def flush(self) -> str:
"""
Expand All @@ -207,9 +252,14 @@ def flush(self) -> str:
c_final_transcript = c_char_p()
status = self._flush_func(self._handle, byref(c_final_transcript))
if status is not self.PicovoiceStatuses.SUCCESS:
raise self._PICOVOICE_STATUS_TO_EXCEPTION[status]()
raise self._PICOVOICE_STATUS_TO_EXCEPTION[status](
message='Flush failed',
message_stack=self._get_error_stack())

final_transcript = c_final_transcript.value.decode('utf-8')
self._transcript_delete_func(c_final_transcript)

return c_final_transcript.value.decode('utf-8')
return final_transcript

def delete(self) -> None:
"""Releases resources acquired by Cheetah."""
Expand All @@ -234,6 +284,21 @@ def frame_length(self) -> int:

return self._frame_length

def _get_error_stack(self) -> Sequence[str]:
message_stack_ref = POINTER(c_char_p)()
message_stack_depth = c_int()
status = self._get_error_stack_func(byref(message_stack_ref), byref(message_stack_depth))
if status is not self.PicovoiceStatuses.SUCCESS:
raise self._PICOVOICE_STATUS_TO_EXCEPTION[status](message='Unable to get Porcupine error state')

message_stack = list()
for i in range(message_stack_depth.value):
message_stack.append(message_stack_ref[i].decode('utf-8'))

self._free_error_stack_func(message_stack_ref)

return message_stack


__all__ = [
'Cheetah',
Expand Down
39 changes: 18 additions & 21 deletions binding/python/setup.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#
# Copyright 2022 Picovoice Inc.
# Copyright 2022-2023 Picovoice Inc.
#
# You may not use this file except in compliance with the license. A copy of the license is located in the "LICENSE"
# file accompanying this source.
Expand All @@ -14,44 +14,41 @@

import setuptools

INCLUDE_FILES = ('../../LICENSE', '__init__.py', '_factory.py', '_cheetah.py', '_util.py')
INCLUDE_LIBS = ('linux', 'mac', 'windows', 'jetson', 'raspberry-pi')

os.system('git clean -dfx')

package_folder = os.path.join(os.path.dirname(__file__), 'pvcheetah')
os.mkdir(package_folder)
manifest_in = ""

shutil.copy(os.path.join(os.path.dirname(__file__), '../../LICENSE'), package_folder)

shutil.copy(os.path.join(os.path.dirname(__file__), '__init__.py'), os.path.join(package_folder, '__init__.py'))
shutil.copy(os.path.join(os.path.dirname(__file__), '_cheetah.py'), os.path.join(package_folder, '_cheetah.py'))
shutil.copy(os.path.join(os.path.dirname(__file__), '_factory.py'), os.path.join(package_folder, '_factory.py'))
shutil.copy(os.path.join(os.path.dirname(__file__), '_util.py'), os.path.join(package_folder, '_util.py'))
for rel_path in INCLUDE_FILES:
shutil.copy(os.path.join(os.path.dirname(__file__), rel_path), package_folder)
manifest_in += "include pvcheetah/%s\n" % os.path.basename(rel_path)

platforms = ('jetson', 'linux', 'mac', 'raspberry-pi', 'windows')
model_file = 'lib/common/cheetah_params.pv'
os.makedirs(os.path.join(package_folder, os.path.split(model_file)[0]))
shutil.copy(
os.path.join(os.path.dirname(__file__), '../..', model_file),
os.path.join(package_folder, model_file))
manifest_in += "include pvcheetah/%s\n" % model_file

os.mkdir(os.path.join(package_folder, 'lib'))
for platform in ('common',) + platforms:
for platform in INCLUDE_LIBS:
shutil.copytree(
os.path.join(os.path.dirname(__file__), '../../lib', platform),
os.path.join(package_folder, 'lib', platform))

MANIFEST_IN = """
include pvcheetah/LICENSE
include pvcheetah/__init__.py
include pvcheetah/_cheetah.py
include pvcheetah/_factory.py
include pvcheetah/_util.py
recursive-include pvcheetah/lib/ *
"""
manifest_in += "recursive-include pvcheetah/lib/%s *\n" % platform

with open(os.path.join(os.path.dirname(__file__), 'MANIFEST.in'), 'w') as f:
f.write(MANIFEST_IN.strip('\n '))
f.write(manifest_in)

with open(os.path.join(os.path.dirname(__file__), 'README.md'), 'r') as f:
long_description = f.read()

setuptools.setup(
name="pvcheetah",
version="1.1.3",
version="2.0.0",
author="Picovoice",
author_email="[email protected]",
description="Cheetah Speech-to-Text Engine.",
Expand Down
Loading