Skip to content

Commit

Permalink
Merge pull request #2 from Picovoice/python-binding
Browse files Browse the repository at this point in the history
Python binding
  • Loading branch information
mrrostam authored Jul 8, 2024
2 parents 0404b0f + 3532043 commit de9c3d7
Show file tree
Hide file tree
Showing 28 changed files with 1,060 additions and 32 deletions.
32 changes: 32 additions & 0 deletions .github/workflows/python-codestyle.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: Python Codestyle

on:
workflow_dispatch:
push:
branches: [ main ]
paths:
- 'binding/python/*.py'
- 'demo/python/*.py'
pull_request:
branches: [ main, 'v[0-9]+.[0-9]+' ]
paths:
- 'binding/python/*.py'
- 'demo/python/*.py'

jobs:
check-python-codestyle:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3

- name: Set up Python 3.11
uses: actions/setup-python@v4
with:
python-version: '3.11'

- name: Install dependencies
run: pip install flake8 pep8-naming

- name: Check python codestyle
run: flake8 --ignore=F401,F403,F405 --max-line-length=120 binding/python demo/python
68 changes: 68 additions & 0 deletions .github/workflows/python-demos.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
name: Python Demos

on:
workflow_dispatch:
push:
branches: [ main ]
paths:
- '.github/workflows/python-demos.yml'
- 'demo/python/**'
- '!demo/python/README.md'
pull_request:
branches: [ main, 'v[0-9]+.[0-9]+' ]
paths:
- '.github/workflows/python-demos.yml'
- 'demo/python/**'
- '!demo/python/README.md'

defaults:
run:
working-directory: demo/python

jobs:
build-github-hosted:
runs-on: ${{ matrix.os }}

strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
python-version: ['3.8', '3.9', '3.10', '3.11', '3.12']

steps:
- uses: actions/checkout@v3

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}

- name: Pre-build dependencies
run: python -m pip install --upgrade pip

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

- name: Run demo
run: python3 pv_speaker_demo.py --show_audio_devices

build-self-hosted:
runs-on: ${{ matrix.machine }}

strategy:
matrix:
machine: [rpi3-32, rpi3-64, rpi4-32, rpi4-64, rpi5-32, rpi5-64]

steps:
- uses: actions/checkout@v3

- name: Install dependencies
run: |
python3 -m venv .venv
source .venv/bin/activate
pip3 install -r requirements.txt
- name: Run demo
run: |
python3 -m venv .venv
source .venv/bin/activate
python3 pv_speaker_demo.py --show_audio_devices
70 changes: 70 additions & 0 deletions .github/workflows/python.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
name: Python

on:
workflow_dispatch:
push:
branches: [ main ]
paths:
- 'binding/python/**'
- '!binding/python/README.md'
- 'lib/linux/**'
- 'lib/mac/**'
- 'lib/raspberry-pi/**'
- 'lib/windows/**'
- '.github/workflows/python.yml'
pull_request:
branches: [ main, 'v[0-9]+.[0-9]+' ]
paths:
- 'binding/python/**'
- '!binding/python/README.md'
- 'lib/linux/**'
- 'lib/mac/**'
- 'lib/raspberry-pi/**'
- 'lib/windows/**'
- '.github/workflows/python.yml'

defaults:
run:
working-directory: binding/python

jobs:
build-github-hosted:
runs-on: ${{ matrix.os }}

strategy:
matrix:
os: [ubuntu-latest]
python-version: ['3.8', '3.9', '3.10', '3.11', '3.12']

steps:
- uses: actions/checkout@v3
with:
submodules: recursive

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}

- name: Test
run: python3 test_pv_speaker.py

build-self-hosted:
runs-on: ${{ matrix.machine }}

strategy:
matrix:
machine: [rpi3-32, rpi3-64, rpi4-32, rpi4-64, rpi5-32, rpi5-64, pv-windows, pv-ios]

steps:
- uses: actions/checkout@v3
with:
submodules: recursive

- name: Test
run: python3 test_pv_speaker.py
if: ${{ matrix.machine != 'pv-windows' }}

- name: Test
run: python test_pv_speaker.py
if: ${{ matrix.machine == 'pv-windows' }}
75 changes: 73 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# PvSpeaker

<!-- markdown-link-check-disable -->
[![PyPI](https://img.shields.io/pypi/v/pvspeaker)](https://pypi.org/project/pvspeaker/)
<!-- markdown-link-check-enable -->

Made in Vancouver, Canada by [Picovoice](https://picovoice.ai)

<!-- markdown-link-check-disable -->
Expand All @@ -14,7 +18,10 @@ PvSpeaker is an easy-to-use, cross-platform audio player designed for real-time
- [Table of Contents](#table-of-contents)
- [Source Code](#source-code)
- [Demos](#demos)
- [C](#c-demo)
- [Python](#python-demo)
- [C](#c-demo)
- [SDKs](#sdks)
- [Python](#python)

## Source Code

Expand All @@ -35,6 +42,30 @@ If using HTTPS, clone the repository with:
git clone --recurse-submodules https://github.com/Picovoice/pvspeaker.git
```

### Python Demo

Install the demo package:

```console
pip3 install pvspeakerdemo
```

To show the available audio devices run:

```console
pv_speaker_demo --show_audio_devices
```

With a working speaker connected to your device run the following in the terminal:

```console
pv_speaker_demo --input_wav_path {INPUT_WAV_PATH}
```

Replace `{INPUT_WAV_PATH}` with the path to the pcm `wav` file you wish to play.

For more information about the Python demos go to [demo/python](demo/python).

### C Demo

Run the following commands to build the demo app:
Expand All @@ -60,4 +91,44 @@ Play from a single-channel PCM WAV file with a given audio device index:

Hit `Ctrl+C` if you wish to stop audio playback before it completes. If no audio device index (`-d`) is provided, the demo will use the system's default audio player device.

For more information about the C demo, go to [demo/c](demo/c).
For more information about the C demo, go to [demo/c](demo/c).

## SDKs

### Python

To start playing audio, initialize an instance and run `start()`:

```python
from pvspeaker import PvSpeaker

speaker = PvSpeaker(
sample_rate=22050,
bits_per_sample=16,
device_index=0)

speaker.start()
```

Write frames of audio:

```python
def get_next_audio_frame():
pass

speaker.write(get_next_audio_frame())
```

When all frames have been written, run `stop()` on the instance:

```python
speaker.stop()
```

Once you are done, free the resources acquired by PvSpeaker. You do not have to call `stop()` before `delete()`:

```python
speaker.delete()
```

For more information about the PvSpeaker Python SDK, go to [binding/python](binding/python).
7 changes: 7 additions & 0 deletions binding/python/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
venv
dist
MANIFEST.in
pvspeaker
pvspeaker.egg-info
build
__pycache__
73 changes: 73 additions & 0 deletions binding/python/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# PvSpeaker Binding for Python

## PvSpeaker

PvSpeaker is an easy-to-use, cross-platform audio player designed for real-time speech audio processing. It allows developers to send raw PCM frames to an audio device's output stream.

## Compatibility

- Python 3.8+
- Runs on Linux (x86_64), macOS (x86_64 and arm64), Windows (x86_64), and Raspberry Pi (3, 4, 5).

## Installation

```shell
pip3 install pvspeaker
```

## Usage

Initialize and start `PvSpeaker`:

```python
from pvspeaker import PvSpeaker

speaker = PvSpeaker(
sample_rate=22050,
bits_per_sample=16,
device_index=0)

speaker.start()
```

(or)

Use `get_available_devices()` to get a list of available devices and then initialize the instance based on the index of a device:

```python
from pvspeaker import PvSpeaker

devices = PvSpeaker.get_available_devices()

speaker = PvSpeaker(
sample_rate=22050,
bits_per_sample=16,
device_index=0)

speaker.start()
```

Write frames of audio:

```python
def get_next_audio_frame():
pass

speaker.write(get_next_audio_frame())
```

When all frames have been written, run `stop()` on the instance:

```python
speaker.stop()
```

Once you are done, free the resources acquired by PvSpeaker. You do not have to call `stop()` before `delete()`:

```python
speaker.delete()
```

## Demos

[pvspeakerdemo](https://pypi.org/project/pvspeakerdemo/) provides command-line utilities for playing audio from a file.
12 changes: 12 additions & 0 deletions binding/python/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#
# Copyright 2024 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.
#
# Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
# an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.
#

from ._pvspeaker import PvSpeaker
Loading

0 comments on commit de9c3d7

Please sign in to comment.