Giter Club home page Giter Club logo

picovoice / porcupine Goto Github PK

View Code? Open in Web Editor NEW
3.5K 63.0 474.0 363.58 MB

On-device wake word detection powered by deep learning

Home Page: https://picovoice.ai/

License: Apache License 2.0

C 4.26% Python 15.57% Java 8.85% C# 11.25% Swift 9.27% JavaScript 8.46% TypeScript 13.61% Ruby 0.71% Shell 0.94% Dart 7.29% Go 8.40% Rust 11.39%
wake-word-detection hotword keyword-spotting keyword-spotter wake-word wake-word-engine handsfree hotword-detection hotword-detector on-device

porcupine's Introduction

Porcupine

GitHub release GitHub

Crates.io Maven Central Maven Central npm npm npm npm npm npm Nuget CocoaPods Pub Version PyPI Go Reference

Made in Vancouver, Canada by Picovoice

Twitter URL YouTube Channel Views

Porcupine is a highly-accurate and lightweight wake word engine. It enables building always-listening voice-enabled applications. It is

  • using deep neural networks trained in real-world environments.
  • compact and computationally-efficient. It is perfect for IoT.
  • cross-platform:
    • Arm Cortex-M, STM32, Arduino, and i.MX RT
    • Raspberry Pi, NVIDIA Jetson Nano, and BeagleBone
    • Android and iOS
    • Chrome, Safari, Firefox, and Edge
    • Linux (x86_64), macOS (x86_64, arm64), and Windows (x86_64)
  • scalable. It can detect multiple always-listening voice commands with no added runtime footprint.
  • self-service. Developers can train custom wake word models using Picovoice Console.

Table of Contents

Use Cases

Porcupine is the right product if you need to detect one or a few static (always-listening) voice commands.

Try It Out

Porcupine in Action

Language Support

  • Arabic, Dutch, English, Farsi, French, German, Hindi, Italian, Japanese, Korean, Mandarin, Polish, Portuguese, Russian, Spanish, Swedish, and Vietnamese
  • Support for additional languages is available for commercial customers on a case-by-case basis.

Performance

A comparison between accuracy and runtime metrics of Porcupine and two other widely-used libraries, PocketSphinx and Snowboy, is provided here. Compared to the best-performing engine of these two, Porcupine is 11.0 times more accurate and 6.5 times faster (on Raspberry Pi 3).

Demos

If using SSH, clone the repository with:

git clone --recurse-submodules [email protected]:Picovoice/porcupine.git

If using HTTPS, clone the repository with:

git clone --recurse-submodules https://github.com/Picovoice/porcupine.git

Python Demos

Install the demo package:

sudo pip3 install pvporcupinedemo

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

porcupine_demo_mic --access_key ${ACCESS_KEY} --keywords porcupine

The engine starts processing the audio input from the microphone in realtime and outputs to the terminal when it detects utterances of Porcupine.

For more information about Python demos go to demo/python.

.NET Demos

From demo/dotnet/PorcupineDemo run the following in the terminal to build the demo:

dotnet build -c MicDemo.Release

Make sure there is a working microphone connected to your device. From demo/dotnet/PorcupineDemo run the following in the terminal:

dotnet run -c MicDemo.Release -- \
--access_key ${ACCESS_KEY} \
--keywords porcupine

The engine starts processing the audio input from the microphone in realtime and outputs to the terminal when it detects utterances of Porcupine.

For more information about .NET demos go to demo/dotnet.

Java Demos

Make sure there is a working microphone connected to your device. Then invoke the following commands from the terminal:

cd demo/java
./gradlew build
cd build/libs
java -jar porcupine-mic-demo.jar -a ${ACCESS_KEY} -k porcupine

The engine starts processing the audio input from the microphone in realtime and outputs to the terminal when it detects utterances of Porcupine.

For more information about Java demos go to demo/java.

Go Demos

The demo requires cgo, which on Windows may mean that you need to install a gcc compiler like Mingw to build it properly.

From demo/go run the following command from the terminal to build and run the mic demo:

go run micdemo/porcupine_mic_demo.go \
-access_key "${ACCESS_KEY}" \
-keywords porcupine

The engine starts processing the audio input from the microphone in realtime and outputs to the terminal when it detects utterances of the word Porcupine.

For more information about Go demos go to demo/go.

Unity Demos

To run the Porcupine Unity demo, import the Porcupine Unity package into your project, open the PorcupineDemo scene and hit play. To run on other platforms or in the player, go to File > Build Settings, choose your platform and hit the Build and Run button.

To browse the demo source go to demo/unity.

Flutter Demos

To run the Porcupine demo on Android or iOS with Flutter, you must have the Flutter SDK installed on your system. Once installed, you can run flutter doctor to determine any other missing requirements for your relevant platform. Once your environment has been set up, launch a simulator or connect an Android/iOS device.

Run the prepare_demo script from demo/flutter with a language code to set up the demo in the language of your choice (e.g. de -> German, ko -> Korean). To see a list of available languages, run prepare_demo without a language code.

dart scripts/prepare_demo.dart ${LANGUAGE}

Replace your AccessKey in lib/main.dart file:

final String accessKey = "{YOUR_ACCESS_KEY_HERE}"; // AccessKey obtained from Picovoice Console (https://console.picovoice.ai/)

Run the following command from demo/flutter to build and deploy the demo to your device:

flutter run

React Native Demos

To run the React Native Porcupine demo app you will first need to set up your React Native environment. For this, please refer to React Native's documentation.

Replace your AccessKey, in App.tsx file:

_accessKey: string ="${YOUR_ACCESS_KEY_HERE}" // AccessKey obtained from Picovoice Console (https://console.picovoice.ai/)

Navigate to demo/react-native to run the following commands:

For Android:

yarn android-install          # sets up environment
yarn android-run ${LANGUAGE}  # builds and deploys to Android

For iOS:

yarn ios-install              # sets up environment
yarn ios-run ${LANGUAGE}      # builds and deploys to iOS

Replace ${LANGUAGE} with the language code of your choice (e.g. de -> German, ko -> Korean). To see a list of available languages, run the android-run or ios-run command without a language code.

Android Demos

Using Android Studio, open demo/android/Activity as an Android project, copy your AccessKey into MainActivity.java, select the build variant (Build > Select Build Variant...) for the desired language and then run the application.

To learn about how to use Porcupine in long-running services go to demo/android/Service.

To learn about how to use Porcupine with Android Speech to Text recognition go to demo/android/STT.

iOS Demos

The BackgroundService demo runs audio recording in the background, enabling detection of wake word while the application is not in focus and remains running in the background. The ForegroundApp demo runs wake word detection only when the application is in focus.

BackgroundService Demo

To run the demo, go to demo/ios/BackgroundService and run:

pod install

Replace let accessKey = "${YOUR_ACCESS_KEY_HERE}" in the file ViewController.swift with your AccessKey.

Then, using Xcode, open the generated PorcupineBackgroundServiceDemo.xcworkspace and run the application.

ForegroundApp Demo

To run the foreground application demo:

  1. Go to ForegroundApp directory. Then run:
pod install
  1. Open the PorcupineForegroundAppDemo.xcworkspace in XCode

  2. Replace let accessKey = "${YOUR_ACCESS_KEY_HERE}" in the file ViewController.swift with your AccessKey.

  3. Go to Product > Scheme and select the scheme for the language you would like to demo (e.g. arDemo -> Arabic Demo, deDemo -> German Demo)

  4. Run the demo with a simulator or connected iOS device

The demo allows you to select any of the pre-built keywords for detection. Press start and say the selected keyword.

Web Demos

Vanilla JavaScript and HTML

From demo/web run the following in the terminal:

yarn
yarn start ${LANGUAGE}

(or)

npm install
npm run start ${LANGUAGE}

Open http://localhost:5000 in your browser to try the demo.

Angular Demos

From demo/angular run the following in the terminal:

yarn
yarn start ${LANGUAGE}

(or)

npm install
npm run start ${LANGUAGE}

Open http://localhost:4200 in your browser to try the demo.

React Demos

From demo/react run the following in the terminal:

yarn
yarn start ${LANGUAGE}

(or)

npm install
npm run start ${LANGUAGE}

Open http://localhost:3000 in your browser to try the demo.

Vue Demos

From demo/vue run the following in the terminal:

yarn
yarn start ${LANGUAGE}

(or)

npm install
npm run start ${LANGUAGE}

Open http://localhost:8080 in your browser to try the demo.

NodeJS Demos

Install the demo package:

yarn global add @picovoice/porcupine-node-demo

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

ppn-mic-demo --access_key ${ACCESS_KEY} --keywords porcupine

The engine starts processing the audio input from the microphone in realtime and outputs to the terminal when it detects utterances of Porcupine.

For more information about NodeJS demos go to demo/nodejs.

Rust Demos

This demo opens an audio stream from a microphone and detects utterances of a given wake word. From demo/rust/micdemo the following opens the default microphone and detects occurrences of "Picovoice":

cargo run --release -- --access_key ${ACCESS_KEY} --keywords picovoice

For more information about Rust demos go to demo/rust.

C Demos

The C demo requires CMake version 3.4 or higher.

The Microphone demo requires miniaudio for accessing microphone audio data.

Windows Requires MinGW to build the demo.

Microphone Demo

At the root of the repository, build with:

cmake -S demo/c/. -B demo/c/build && cmake --build demo/c/build --target porcupine_demo_mic

Linux (x86_64), macOS (x86_64), Raspberry Pi, BeagleBone, and Jetson

List input audio devices with:

./demo/c/build/porcupine_demo_mic --show_audio_devices

Run the demo using:

./demo/c/build/porcupine_demo_mic -l ${LIBRARY_PATH} -m lib/common/porcupine_params.pv \
-k resources/keyword_files/${PLATFORM}/porcupine_${PLATFORM}.ppn -t 0.5 \
-d ${AUDIO_DEVICE_INDEX} -a ${ACCESS_KEY}

Replace ${LIBRARY_PATH} with path to appropriate library available under lib, ${PLATFORM} with the name of the platform you are running on (linux, raspberry-pi, mac, beaglebone, or jetson), ${AUDIO_DEVICE_INDEX} with the index of your audio device and ${ACCESS_KEY} with your AccessKey.

Windows

List input audio devices with:

.\\demo\\c\\build\\porcupine_demo_mic.exe --show_audio_devices

Run the demo using:

.\\demo\\c\\build\\porcupine_demo_mic.exe ^
-l lib/windows/amd64/libpv_porcupine.dll ^
-m lib/common/porcupine_params.pv ^
-k resources/keyword_files/windows/porcupine_windows.ppn ^
-t 0.5 ^
-d ${AUDIO_DEVICE_INDEX} ^
-a ${ACCESS_KEY}

Replace ${AUDIO_DEVICE_INDEX} with the index of your audio device and ${ACCESS_KEY} with your AccessKey.

The demo opens an audio stream and detects utterances of Porcupine.

File Demo

At the root of the repository, build with:

cmake -S demo/c/. -B demo/c/build && cmake --build demo/c/build --target porcupine_demo_file

Linux (x86_64), macOS (x86_64), Raspberry Pi, BeagleBone, and Jetson

Run the demo using:

./demo/c/build/porcupine_demo_file -l ${LIBRARY_PATH} -m lib/common/porcupine_params.pv \
-k resources/keyword_files/${PLATFORM}/porcupine_${PLATFORM}.ppn -t 0.5 \
-w resources/audio_samples/multiple_keywords.wav -a ${ACCESS_KEY}

Replace ${LIBRARY_PATH} with path to appropriate library available under lib, ${PLATFORM} with the name of the platform you are running on (linux, raspberry-pi, mac, beaglebone, or jetson) and ${ACCESS_KEY} with your AccessKey.

Windows

Run the demo using:

.\\demo\\c\\build\\porcupine_demo_file.exe ^
-l lib/windows/amd64/libpv_porcupine.dll ^
-m lib/common/porcupine_params.pv ^
-k resources/keyword_files/windows/porcupine_windows.ppn ^
-t 0.5 ^
-w resources/audio_samples/multiple_keywords.wav ^
-a ${ACCESS_KEY}

Replace ${ACCESS_KEY} with your AccessKey.

The demo opens up the file and detects utterances of Porcupine.

For more information about C demos go to demo/c.

Microcontroller Demos

There are several projects for various development boards inside the mcu demo folder.

SDKs

Python

Install the Python SDK:

pip3 install pvporcupine

The SDK exposes a factory method to create instances of the engine:

import pvporcupine

# AccessKey obtained from Picovoice Console (https://console.picovoice.ai/)
access_key = "${ACCESS_KEY}"

handle = pvporcupine.create(access_key=access_key, keywords=['picovoice', 'bumblebee'])

keywords argument is a shorthand for accessing default keyword files shipped with the library. The default keyword files available can be retrieved via

import pvporcupine

print(pvporcupine.KEYWORDS)

If you wish to use a non-default keyword file you need to identify its path:

import pvporcupine

# AccessKey obtained from Picovoice Console (https://console.picovoice.ai/)
access_key = "${ACCESS_KEY}"

handle = pvporcupine.create(
    access_key=access_key,
    keyword_paths=['path/to/non/default/keyword/file'])

When initialized, valid sample rate can be obtained using handle.sample_rate. The required frame length (number of audio samples in an input array) is handle.frame_length. The object can be used to monitor incoming audio as follows:

import pvporcupine

# AccessKey obtained from Picovoice Console (https://console.picovoice.ai/)
access_key = "${ACCESS_KEY}"

handle = pvporcupine.create(access_key=access_key, keywords=['porcupine'])

def get_next_audio_frame():
    pass

while True:
    keyword_index = handle.process(get_next_audio_frame())
    if keyword_index >= 0:
        # Insert detection event callback here
        pass

Finally, when done be sure to explicitly release the resources using handle.delete().

.NET

Install the .NET SDK using NuGet or the dotnet CLI:

dotnet add package Porcupine

The SDK exposes a factory method to create instances of the engine:

using Pv;

const string accessKey = "${ACCESS_KEY}";
var keyword = new List<BuiltInKeyword> { BuiltInKeyword.PICOVOICE };

Porcupine handle = Porcupine.FromBuiltInKeywords(accessKey, keyword);

Using the FromBuiltInKeywords constructor allows you to initialize the Porcupine engine to detect any of the free, built-in keywords that come with the library. These built-ins are represented by the BuiltInKeyword enum.

If you wish to use a custom keyword file (i.e. a keyword file generated by Picovoice Console, with a .ppn extension), you need to specify its path:

const string accessKey = "${ACCESS_KEY}";
var keywordPaths = new List<string> {
    "/absolute/path/to/keyword/one",
    "/absolute/path/to/keyword/two",
    ... }

Porcupine handle = Porcupine.FromKeywordPaths(accessKey, keywordPaths);

When initialized, the required sample rate can be obtained using handle.SampleRate. Expected frame length (number of audio samples in an input array) is handle.FrameLength. The object can be used to monitor incoming audio as below:

short[] getNextAudioFrame()
{
    // .. get a frame of audio
    return audioFrame;
}

while(true)
{
    var keywordIndex = handle.Process(getNextAudioFrame())
    if(keywordIndex >= 0)
    {
        // .. Insert detection event callback here
    }
}

Porcupine will have its resources freed by the garbage collector, but to have resources freed immediately after use, wrap it in a using statement:

using(Porcupine handle = Porcupine.FromBuiltInKeywords(
    accessKey,
    new List<BuiltInKeyword> { BuiltInKeyword.PICOVOICE }))
{
    // .. Porcupine usage here
}

Java

The Porcupine Java binding is available from the Maven Central Repository at ai.picovoice:porcupine-java:${version}.

import ai.picovoice.porcupine.*;

// AccessKey obtained from Picovoice Console (https://console.picovoice.ai/)
final String accessKey = "${ACCESS_KEY}";
try {
    Porcupine handle = new Porcupine.Builder()
                        .setAccessKey(accessKey)
                        .setBuiltInKeyword(BuiltInKeyword.PORCUPINE)
                        .build();
} catch (PorcupineException e) { }

The setBuiltInKeyword() builder argument is a shorthand for accessing built-in keyword model files shipped with the package.

The list of built-in keywords can be found in the BuiltInKeyword enum, and can be retrieved by:

import ai.picovoice.porcupine.*;

for(BuiltInKeyword keyword : BuiltInKeyword.values()) {
    System.out.println(keyword.name());
}

If you wish to use a custom keyword file (i.e. a keyword file generated by Picovoice Console, with a .ppn extension) you need to the file path as demonstrated below:

import ai.picovoice.porcupine.*;

// AccessKey obtained from Picovoice Console (https://console.picovoice.ai/)
final String accessKey = "${ACCESS_KEY}";
try {
    Porcupine handle = new Porcupine.Builder()
                        .setAccessKey(accessKey)
                        .setKeywordPath("path/to/custom/keyword/file")
                        .build();
} catch (PorcupineException e) { }

When initialized, valid sample rate can be obtained using handle.getSampleRate(). Expected frame length (number of audio samples in an input array) is handle.getFrameLength(). The object can be used to monitor incoming audio as below:

short[] getNextAudioFrame() {
    // .. get audioFrame
    return audioFrame;
}

while(true) {
    int keywordIndex = handle.Process(getNextAudioFrame());
    if(keywordIndex >= 0) {
        // .. detection event logic/callback
    }
}

Once you're done with Porcupine, ensure you release its resources explicitly:

handle.delete();

Go

To install the Porcupine Go module to your project, use the command:

go get github.com/Picovoice/porcupine/binding/go

To create an instance of the engine you first create a Porcupine struct with the configuration parameters for the wake word engine and then make a call to .Init().

import . "github.com/Picovoice/porcupine/binding/go/v2"

porcupine := Porcupine{
  AccessKey: "${ACCESS_KEY}", // from Picovoice Console (https://console.picovoice.ai/)
  BuiltInKeywords: []BuiltInKeyword{PICOVOICE}}
err := porcupine.Init()
if err != nil {
    // handle init fail
}

In the above example, we've initialized the engine to detect the built-in wake word "Picovoice". Built-in keywords are constants in the package with the BuiltInKeyword type.

To detect non-default keywords, use KeywordPaths parameter instead

porcupine := Porcupine{
  AccessKey: "${ACCESS_KEY}", // from Picovoice Console (https://console.picovoice.ai/)
  KeywordPaths: []string{"/path/to/keyword.ppn"}}
err := porcupine.Init()

When initialized, the valid sample rate is given by SampleRate. Expected frame length (number of audio samples in an input array) is given by FrameLength. The engine accepts 16-bit linearly-encoded PCM and operates on single-channel audio.

To feed audio into Porcupine, use the Process function in your capture loop. You must call Init() before calling Process.

func getNextFrameAudio() []int16 {
    // get audio frame
}

for {
    keywordIndex, err := porcupine.Process(getNextFrameAudio())
    if keywordIndex >= 0 {
        // wake word detected!
    }
}

When done resources have to be released explicitly.

porcupine.Delete()

Unity

Import the Porcupine Unity Package into your Unity project.

The SDK provides two APIs:

High-Level API

PorcupineManager provides a high-level API that takes care of audio recording. This is the quickest way to get started.

The static constructor PorcupineManager.FromBuiltInKeywords will create an instance of the PorcupineManager using one or more of the built-in keywords.

using Pv.Unity;

// AccessKey obtained from Picovoice Console (https://console.picovoice.ai/)
string accessKey = "${ACCESS_KEY}";

try {
    List<Porcupine.BuiltInKeyword> keywords = new List<Porcupine.BuiltInKeyword>(){
        Porcupine.BuiltInKeyword.PICOVOICE,
        Porcupine.BuiltInKeyword.PORCUPINE
    };
    PorcupineManager _porcupineManager = PorcupineManager.FromBuiltInKeywords(
                                            accessKey,
                                            keywords,
                                            OnWakeWordDetected);
}
catch (Exception ex)
{
    // handle porcupine init error
}

To create an instance of PorcupineManager that detects custom keywords, you can use the PorcupineManager.FromKeywordPaths static constructor and provide the paths to the .ppn file(s).

// AccessKey obtained from Picovoice Console (https://console.picovoice.ai/)
string accessKey = "${ACCESS_KEY}";

List<string> keywordPaths = new List<string>(){ "/path/to/keyword.ppn" };
PorcupineManager _porcupineManager = PorcupineManager.FromKeywordPaths(
                                        accessKey,
                                        keywordPaths,
                                        OnWakeWordDetected);

Once you have instantiated a PorcupineManager, you can start/stop audio capture and wake word detection by calling:

_porcupineManager.Start();
// .. use porcupine
_porcupineManager.Stop();

Once the app is done with using PorcupineManager, you can explicitly release the resources allocated to Porcupine:

_porcupineManager.Delete();

There is no need to deal with audio capture to enable wake word detection with PorcupineManager. This is because it uses our unity-voice-processor Unity package to capture frames of audio and automatically pass it to the wake word engine.

Low-Level API

Porcupine provides low-level access to the wake word engine for those who want to incorporate wake word detection into an already existing audio processing pipeline. To create an instance of Porcupine, use the .FromBuiltInKeywords static constructor.

using Pv.Unity;

// AccessKey obtained from Picovoice Console (https://console.picovoice.ai/)
string accessKey = "${ACCESS_KEY}";

try
{
    List<Porcupine.BuiltInKeyword> keywords = new List<Porcupine.BuiltInKeyword>(){
        Porcupine.BuiltInKeyword.PORCUPINE,
        Porcupine.BuiltInKeyword.PICOVOICE
    };
    Porcupine _porcupine = Porcupine.FromBuiltInKeywords(
        accessKey: accessKey,
        keywords: keywords);
}
catch (Exception ex)
{
    // handle porcupine init error
}

To search for a keyword in audio, you must pass frames of audio to Porcupine using the Process function. The keywordIndex returned will either be -1 if no detection was made or an integer specifying which keyword was detected.

short[] frame = getAudioFrame();

try
{
    int keywordIndex = _porcupine.Process(frame);
    if (keywordIndex >= 0)
    {
        // detection made!
    }
}
catch (Exception ex)
{
    Debug.LogError(ex.ToString());
}

For Process to work correctly, the provided audio must be single-channel and 16-bit linearly-encoded.

Finally, once you no longer need the wake word engine, you can explicitly release the resources allocated to Porcupine:

_porcupine.Dispose();

Flutter

Add the Porcupine Flutter plugin to your pub.yaml.

dependencies:
  flutter_porcupine: ^<version>

The SDK provides two APIs:

High-Level API

PorcupineManager provides a high-level API that takes care of audio recording. This class is the quickest way to get started.

The static constructor PorcupineManager.fromBuiltInKeywords will create an instance of the PorcupineManager using one or more of the built-in keywords.

import 'package:porcupine_flutter/porcupine_manager.dart';
import 'package:porcupine_flutter/porcupine_error.dart';

// AccessKey obtained from Picovoice Console (https://console.picovoice.ai/)
final String accessKey = "{ACCESS_KEY}";

void createPorcupineManager() async {
    try {
        _porcupineManager = await PorcupineManager.fromBuiltInKeywords(
            accessKey,
            [BuiltInKeyword.PICOVOICE, BuiltInKeyword.PORCUPINE],
            _wakeWordCallback);
    } on PorcupineException catch (err) {
        // handle porcupine init error
    }
}

To create an instance of PorcupineManager that detects custom keywords, you can use the PorcupineManager.fromKeywordPaths static constructor and provide the paths to the .ppn file(s).

 // AccessKey obtained from Picovoice Console (https://console.picovoice.ai/)
final String accessKey = "{ACCESS_KEY}";

_porcupineManager = await PorcupineManager.fromKeywordPaths(
    accessKey,
    ["/path/to/keyword.ppn"],
    _wakeWordCallback);

Once you have instantiated a PorcupineManager, you can start/stop audio capture and wake word detection by calling:

try {
    await _porcupineManager.start();
} on PorcupineException catch (ex) {
    // deal with either audio exception
}
// .. use porcupine
await _porcupineManager.stop();

Once the app is done with using PorcupineManager, be sure you explicitly release the resources allocated to Porcupine:

await _porcupineManager.delete();

There is no need to deal with audio capture to enable wake word detection with PorcupineManager. This is because it uses flutter_voice_processor plugin to capture frames of audio and automatically pass it to the wake word engine.

Low-Level API

Porcupine provides low-level access to the wake word engine for those who want to incorporate wake word detection into an already existing audio processing pipeline.Porcupine has fromBuiltInKeywords and fromKeywordPaths static constructors.

import 'package:porcupine_flutter/porcupine_manager.dart';
import 'package:porcupine_flutter/porcupine_error.dart';

// AccessKey obtained from Picovoice Console (https://console.picovoice.ai/)
final String accessKey = "{ACCESS_KEY}";

void createPorcupine() async {
    try {
        _porcupine = await Porcupine.fromBuiltInKeywords(
          accessKey,
          [BuiltInKeyword.PICOVOICE]);
    } on PorcupineException catch (err) {
        // handle porcupine init error
    }
}

To search for a keyword in audio, you must pass frames of audio to Porcupine using the process function. The keywordIndex returned will either be -1 if no detection was made or an integer specifying which keyword was detected.

List<int> buffer = getAudioFrame();

try {
    int keywordIndex = _porcupine.process(buffer);
    if (keywordIndex >= 0) {
        // detection made!
    }
} on PorcupineException catch (error) {
    // handle error
}

For process to work correctly, the provided audio must be single-channel and 16-bit linearly-encoded.

Finally, once you no longer need the wake word engine, be sure to explicitly release the resources allocated to Porcupine:

_porcupine.delete();

React Native

Install @picovoice/react-native-voice-processor and @picovoice/porcupine-react-native. The SDK provides two APIs:

High-Level API

PorcupineManager provides a high-level API that takes care of audio recording. This class is the quickest way to get started.

Using the constructor PorcupineManager.fromBuiltInKeywords will create an instance of the PorcupineManager using one or more of the built-in keywords.

 // AccessKey obtained from Picovoice Console (https://console.picovoice.ai/)
const accessKey = "${ACCESS_KEY}";

async createPorcupineManager(){
    try {
        this._porcupineManager = await PorcupineManager.fromBuiltInKeywords(
            accessKey,
            [BuiltInKeywords.Picovoice, BuiltInKeywords.Porcupine],
            detectionCallback,
            processErrorCallback);
    } catch (err) {
        // handle error
    }
}

To create an instance of PorcupineManager that detects custom keywords, you can use the PorcupineManager.fromKeywordPaths static constructor and provide the paths to the .ppn file(s).

// AccessKey obtained from Picovoice Console (https://console.picovoice.ai/)
const accessKey = "${ACCESS_KEY}";

this._porcupineManager = await PorcupineManager.fromKeywordPaths(
  accessKey,
  ["/path/to/keyword.ppn"],
  detectionCallback,
  processErrorCallback
);

Once you have instantiated a Porcupine manager, you can start/stop audio capture and wake word detection by calling:

let didStart = this._porcupineManager.start();
// .. use Porcupine
let didStop = this._porcupineManager.stop();

Once the app is done with using PorcupineManager, be sure you explicitly release the resources allocated to Porcupine:

this._porcupineManager.delete();

There is no need to deal with audio capture to enable wake word detection with PorcupineManager. This is because it uses @picovoice/react-native-voice-processor module to capture frames of audio and automatically pass it to the wake word engine.

Low-Level API

Porcupine provides low-level access to the wake word engine for those who want to incorporate wake word detection into an already existing audio processing pipeline. Porcupine also has fromBuiltInKeywords and fromKeywordPaths static constructors.

// AccessKey obtained from Picovoice Console (https://console.picovoice.ai/)
const accessKey = "${ACCESS_KEY}";

async createPorcupine(){
    try {
        this._porcupine = await Porcupine.fromBuiltInKeywords(
            accessKey, [BuiltInKeywords.PICOVOICE]);
    } catch (err) {
        // handle error
    }
}

To search for a keyword in audio, you must pass frames of audio to Porcupine using the process function. The keywordIndex returned will either be -1 if no detection was made or an integer specifying which keyword was detected.

let buffer = getAudioFrame();

try {
  let keywordIndex = await this._porcupine.process(buffer);
  if (keywordIndex >= 0) {
    // detection made!
  }
} catch (e) {
  // handle error
}

For process to work correctly, the provided audio must be single-channel and 16-bit linearly-encoded.

Finally, once you no longer need the wake word engine, be sure to explicitly release the resources allocated to Porcupine:

this._porcupine.delete();

Android

To include the package in your Android project, ensure you have included mavenCentral() in your top-level build.gradle file and then add the following to your app's build.gradle:

dependencies {
    implementation 'ai.picovoice:porcupine-android:${LATEST_VERSION}'
}

There are two possibilities for integrating Porcupine into an Android application.

High-Level API

PorcupineManager provides a high-level API for integrating Porcupine into Android applications. It manages all activities related to creating an input audio stream, feeding it into the Porcupine library, and invoking a user-provided detection callback.

import ai.picovoice.porcupine.*;

final String accessKey = "${ACCESS_KEY}"; // AccessKey obtained from Picovoice Console (https://console.picovoice.ai/)
final String keywordPath = "/path/to/keyword.ppn"; // path relative to 'assets' folder

try {
    PorcupineManager porcupineManager = new PorcupineManager.Builder()
                        .setAccessKey(accessKey)
                        .setKeywordPath(keywordPath)
                        .setSensitivity(0.5f)
                        .build(context,
                        new PorcupineManagerCallback() {
                            @Override
                            public void invoke(int keywordIndex) {
                                // detection event logic/callback
                            }
                        });
} catch (PorcupineException e) { }

Keyword files (.ppn) should be placed under the Android project assets folder (src/main/assets/).

Sensitivity is the parameter that enables developers to trade miss rate for false alarm. It is a floating point number within [0, 1]. A higher sensitivity reduces miss rate at cost of increased false alarm rate.

When initialized, input audio can be monitored using manager.start(). Stop the manager using by invoking manager.stop(). When done be sure to release the resources using manager.delete().

Low-Level API

Porcupine provides a binding for Android. It can be initialized using:

import ai.picovoice.porcupine.*;

final String accessKey = "${ACCESS_KEY}";
final String keywordPath = "/path/to/keyword.ppn";
try {
    Porcupine porcupine = new Porcupine.Builder()
                        .setAccessKey(accessKey)
                        .setKeywordPath(keywordPath)
                        .setSensitivity(0.5f)
                        .build(context);
} catch (PorcupineException e) { }

Once initialized, porcupine can be used to monitor incoming audio.

private short[] getNextAudioFrame();

while (true) {
    final int keywordIndex = porcupine.process(getNextAudioFrame());
    if (keywordIndex != -1) {
        // detection event logic/callback
    }
}

Finally, be sure to explicitly release resources acquired by porcupine as the binding class does not rely on the garbage collector for releasing native resources.

porcupine.delete();

iOS

There are two approaches for integrating Porcupine into an iOS application.

High-Level API

PorcupineManager manages audio recording, passing it into Porcupine, and invoking the user-provided detection callback.

let accessKey = "${ACCESS_KEY}" // Obtained from Picovoice Console (https://console.picovoice.ai)
let modelPath: String = ... // Available at lib/common/porcupine_params.pv
let keywordPaths: [String] = ["/path/to/keyword/file/a", "/path/to/keyword/file/b"]
let sensitivities: [Float32] = [0.35, 0.64]
let keywordCallback: ((Int32) -> Void) = { keywordIndex in
    // Insert detection event logic
}

let manager = try PorcupineManager(
    accessKey: accessKey,
    modelPath: modelPath,
    keywordPaths: keywordPaths,
    sensitivities: sensitivities
    onDetection: keywordCallback)

When initialized, input audio can be monitored using manager.start(). When done be sure to stop the manager using manager.stop().

Low-Level API

Porcupine.swift provides low-level access to the wake word engine for those who want to incorporate wake word detection into an already existing audio processing pipeline.

To construct an instance of Porcupine, pass it a keyword.

import Porcupine

let accessKey = "${ACCESS_KEY}" // Obtained from Picovoice Console (https://console.picovoice.ai)

do {
    Porcupine porcupine = try Porcupine(
      accessKey: accessKey,
      keyword: Porcupine.BuiltInKeyword.picovoice)
} catch { }

To search for a keyword in audio, you must pass frames of audio to Porcupine using the process function. The keywordIndex returned will either be -1 if no detection was made or an integer specifying which keyword was detected.

func getNextAudioFrame() -> [Int16] {
    // .. get audioFrame
    return audioFrame;
}

while true {
    do {
        let keywordIndex = try porcupine.process(getNextAudioFrame())
        if keywordIndex >= 0 {
            // .. detection made!
        }
    } catch { }
}

Once you're done with Porcupine you can force it to release its native resources rather than waiting for the garbage collector:

porcupine.delete();

Web

Porcupine is available on modern web browsers (i.e. not Internet Explorer) via WebAssembly. Microphone audio is handled via the Web Audio API and is abstracted by the WebVoiceProcessor, which also handles downsampling to the correct format. Porcupine is provided pre-packaged as a Web Worker.

Each spoken language is available as a dedicated npm package (e.g. @picovoice/porcupine-web-en-worker). These packages can be used with the @picovoice/web-voice-processor. They can also be used with the Angular, React, and Vue bindings, which abstract and hide the web worker communication details.

Vanilla JavaScript and HTML (CDN Script Tag)

<!DOCTYPE html>
<html lang="en">
<head>
  <script src="https://unpkg.com/@picovoice/porcupine-web/dist/iife/index.js"></script>
  <script src="https://unpkg.com/@picovoice/web-voice-processor/dist/iife/index.js"></script>
  <script type="application/javascript">

    const PORCUPINE_MODEL_BASE64 = /* Base64 representation of the `.pv` model file*/;

    function keywordDetectionCallback(detection) {
      console.log(`Porcupine detected ${detection.label}`);
    }

    function processErrorCallback(error) {
      console.error(error);
    }

    async function startPorcupine() {
      console.log("Porcupine is loading. Please wait...");
      const accessKey = "${ACCESS_KEY}" // Obtained from Picovoice Console (picovoice.ai/console/)
      let porcupine = await PorcupineWeb.PorcupineWorker.create(
              accessKey,
              [PorcupineWeb.BuiltInKeyword.Picovoice],
              porcupineKeywordCallback,
              { base64: PORCUPINE_MODEL_BASE64 },
      );

      console.log("Porcupine worker ready!");

      console.log("WebVoiceProcessor initializing. Microphone permissions requested ...");
      await window.WebVoiceProcessor.WebVoiceProcessor.subscribe(porcupine);
      console.log("WebVoiceProcessor ready and listening!");

      document.addEventListener("DOMContentLoaded", function () {
        startPorcupine();
      });
  </script>
</head>
<body></body>
</html>

Vanilla JavaScript and HTML (ES Modules)

Install the web SDK using yarn:

yarn add @picovoice/porcupine-web @picovoice/web-voice-processor

(or)

npm install --save @picovoice/porcupine-web @picovoice/web-voice-processor
import { WebVoiceProcessor } from "@picovoice/web-voice-processor"
import { PorcupineWorker } from "@picovoice/porcupine-web";

const PORCUPINE_MODEL_BASE64 = /* Base64 representation of the `.pv` model file*/;

function keywordDetectionCallback(detection) {
  console.log(`Porcupine detected ${detection.label}`);
}

const porcupine = await PorcupineWorker.create(
  "${ACCESS_KEY}",
  PorcupineWeb.BuiltInKeyword.Porcupine,
  keywordDetectionCallback,
  { base64: PORCUPINE_MODEL_BASE64 },
);

console.log("WebVoiceProcessor initializing. Microphone permissions requested ...");
await WebVoiceProcessor.subscribe(porcupine);
console.log("WebVoiceProcessor ready and listening!");

...

// Finished with Porcupine? Release the WebVoiceProcessor and the worker.
if (done) {
  await WebVoiceProcessor.unsubscribe(porcupine);
  porcupine.release()
  porcupine.terminate()
}

Angular

yarn add @picovoice/porcupine-angular @picovoice/web-voice-processor

(or)

npm install @picovoice/porcupine-angular @picovoice/web-voice-processor
import { Subscription } from "rxjs";
import { PorcupineService } from "@picovoice/porcupine-web-angular";
import {BuiltInKeyword} from '@picovoice/porcupine-web';
import porcupineParams from "${PATH_TO_PORCUPINE_PARAMS_BASE64}";

constructor(private porcupineService: PorcupineService) {
  this.keywordSubscription = porcupineService.keyword$.subscribe(
    porcupineDetection => {
      console.log(`Porcupine Detected "${porcupineDetection.label}"`)
    });
  this.isLoadedSubscription = porcupineService.isLoaded$.subscribe(
    isLoaded => {
      console.log(isLoaded);
    });
  this.isListeningSubscription = porcupineService.isListening$.subscribe(
    isListening => {
      console.log(isListening);
    });
  this.errorSubscription = porcupineService.error$.subscribe(
    error => {
      console.error(error);
    });
}

async ngOnInit() {
  await this.porcupineService.init(
    ${ACCESS_KEY},
    [BuiltInKeyword.Porcupine],
    porcupineModel,
    options
  ).then(() => {
    this.porcupineService.start();
  });
}

ngOnDestroy() {
  this.keywordSubscription.unsubscribe();
  this.isLoadedSubscription.unsubscribe();
  this.isListeningSubscription.unsubscribe();
  this.errorSubscription.unsubscribe();
  this.porcupineService.release();
}

React

yarn add @picovoice/porcupine-react @picovoice/web-voice-processor

(or)

npm install @picovoice/porcupine-react @picovoice/web-voice-processor
import { BuiltInKeyword } from '@picovoice/porcupine-web';
import { usePorcupine } from '@picovoice/porcupine-react';

function App(props) {
  const {
    wakeWordDetection,
    isLoaded,
    isListening,
    error,
    init,
    start,
    stop,
    release,
  } = usePorcupine();

  const initEngine = async () => {
    await init(
      ${ACCESS_KEY},
      [BuiltInKeyword.Porcupine],
      porcupineModel
    );
    await start();
  }

  useEffect(() => {
    if (wakeWordDetection !== null) {
      console.log(wakeWordDetection.label);
    }
  }, [wakeWordDetection])
}

Vue

yarn add @picovoice/porcupine-vue @picovoice/web-voice-processor

(or)

npm install @picovoice/porcupine-vue @picovoice/web-voice-processor
<script lang='ts'>
import { BuiltInKeyword } from '@picovoice/porcupine-web';
import { usePorcupine } from '@picovoice/porcupine-vue';

import porcupineParams from "${PATH_TO_PORCUPINE_PARAMS_BASE64}"

// Use Vue.extend for JavaScript
export default {
  data() {
    const {
      state,
      init,
      start,
      stop,
      release
    } = usePorcupine();

    init(
      ${ACCESS_KEY},
      [BuiltInKeyword.Porcupine],
      { base64: porcupineParams }, // porcupine model
    );

    return {
      state,
      start,
      stop,
      release
    }
  },
  watch: {
    "state.keywordDetection": function (keyword) {
      if (keyword !== null) {
        console.log(keyword.label);
      }
    },
    "state.isLoaded": function (isLoaded) {
      console.log(isLoaded)
    },
    "state.isListening": function (isListening) {
      console.log(isListening)
    },
    "state.error": function (error) {
      console.error(error)
    },
  },
  onBeforeDestroy() {
    this.release();
  },
};
</script>

NodeJS

Install NodeJS SDK:

yarn add @picovoice/porcupine-node

Create instances of the Porcupine class by specifying which keywords you want it to listen for:

const {
  Porcupine,
  BuiltinKeyword,
}= require("@picovoice/porcupine-node");

 // Obtained from the Picovoice Console (https://console.picovoice.ai/)
const accessKey = "${ACCESS_KEY}";

let handle = new Porcupine(
    accessKey,
    [BuiltinKeyword.GRASSHOPPER, BuiltinKeyword.BUMBLEBEE],
    [0.5, 0.65]);

GRASSHOPPER and BUMBLEBEE are built-in keywords. If you wish to use a custom keyword file, you need to identify its path:

const Porcupine = require("@picovoice/porcupine-node");

 // Obtained from the Picovoice Console (https://console.picovoice.ai/)
const accessKey = "${ACCESS_KEY}";

let handle = new Porcupine(
    accessKey,
    ["/path/to/custom/keyword/file"],
    [0.5]);

When instantiated, handle can process audio via its .process method.

let getNextAudioFrame = function() {
    ...
};

while (true) {
  let keywordIndex = handle.process(getNextAudioFrame());
  if (keywordIndex !== -1) {
    // detection event callback
  }
}

When done be sure to release resources acquired by WebAssembly using release():

handle.release();

Rust

First you will need Rust and Cargo installed on your system.

To add the porcupine library into your app, add pv_porcupine to your apps Cargo.toml manifest:

[dependencies]
pv_porcupine = "*"

To create an instance of the engine you first create a PorcupineBuilder instance with the configuration parameters for the wake word engine and then make a call to .init():

use porcupine::{BuiltinKeywords, PorcupineBuilder};

// AccessKey obtained from Picovoice Console (https://console.picovoice.ai/)
let access_key = "${ACCESS_KEY}";

let porcupine: Porcupine = PorcupineBuilder::new_with_keywords(
        access_key,
        &[BuiltinKeywords::Porcupine]
    )
    .init()
    .expect("Unable to create Porcupine");

In the above example, we've initialized the engine to detect the built-in wake word "Porcupine". Built-in keywords are contained in the package with the BuiltinKeywords enum type.

To detect custom keywords, use PorcupineBuilder's new_with_keyword_paths method to pass in *.ppn file paths instead:

let porcupine: Porcupine = PorcupineBuilder::new_with_keyword_paths(
        &["/absolute/path/to/keyword/one.ppn",
        "/absolute/path/to/keyword/two.ppn"]
    )
    .init()
    .expect("Unable to create Porcupine");

When initialized, the valid sample rate is given by sample_rate(). Expected frame length (number of audio samples in an input array) is given by frame_length(). The engine accepts 16-bit linearly-encoded PCM and operates on single-channel audio.

To feed audio into Porcupine, use the process function in your capture loop:

fn next_audio_frame() -> Vec<i16> {
    // get audio frame
}

loop {
    if let Ok(keyword_index) = porcupine.process(&next_audio_frame()) {
        if keyword_index >= 0 {
            // wake word detected!
        }
    }
}

C

Porcupine is implemented in ANSI C and therefore can be directly linked to C applications. include/pv_porcupine.h header file contains relevant information. An instance of Porcupine object can be constructed as follows.

// Available at lib/common/porcupine_params.pv
const char *model_path = ...
// AccessKey obtained from Picovoice Console (https://console.picovoice.ai/)
const char *access_key = ...
const char *keyword_path = ...
const float sensitivity = 0.5f;

pv_porcupine_t *handle = NULL;
const pv_status_t status = pv_porcupine_init(
    access_key,
    model_path,
    1,
    &keyword_path,
    &sensitivity,
    &handle);
if (status != PV_STATUS_SUCCESS) {
    // Insert error handling logic
}

Sensitivity is the parameter that enables developers to trade miss rate for false alarm. It is a floating point number within [0, 1]. A higher sensitivity reduces miss rate (false reject rate) at cost of (potentially) increased false alarm rate.

Now the handle can be used to monitor incoming audio stream. Porcupine accepts single channel, 16-bit linearly-encoded PCM audio. The sample rate can be retrieved using pv_sample_rate(). Finally, Porcupine accepts input audio in consecutive chunks (aka frames) the length of each frame can be retrieved using pv_porcupine_frame_length().

extern const int16_t *get_next_audio_frame(void);

while (true) {
    const int16_t *pcm = get_next_audio_frame();
    int32_t keyword_index = -1;
    const pv_status_t status = pv_porcupine_process(handle, pcm, &keyword_index);
    if (status != PV_STATUS_SUCCESS) {
        // error handling logic
    }
    if (keyword_index != -1) {
        // Insert detection event callback
    }
}

Finally, when done be sure to release the acquired resources:

pv_porcupine_delete(handle);

Microcontroller

Porcupine is implemented in ANSI C and therefore can be directly linked to embedded C projects. Its public header file contains relevant information. An instance of the Porcupine object can be constructed as follows.

#define MEMORY_BUFFER_SIZE ...
uint8_t memory_buffer[MEMORY_BUFFER_SIZE] __attribute__((aligned(16)));

// AccessKey string obtained from Picovoice Console (https://console.picovoice.ai/)
static const char* ACCESS_KEY = ...

const uint8_t keyword_array[] = {...};

const int32_t keyword_model_sizes = sizeof(keyword_array);
const void *keyword_models = keyword_array;
const float sensitivity = 0.5f;

pv_porcupine_t *handle = NULL;

const pv_status_t status = pv_porcupine_init(
        ACCESS_KEY,
        MEMORY_BUFFER_SIZE,
        memory_buffer,
        1,
        &keyword_model_sizes,
        &keyword_models,
        &sensitivity,
        &handle);

if (status != PV_STATUS_SUCCESS) {
    // error handling logic
}

Sensitivity is the parameter that enables developers to trade miss rate for false alarm. It is a floating-point number within [0, 1]. A higher sensitivity reduces miss rate (false reject rate) at cost of increased false alarm rate.

Now the handle can be used to monitor incoming audio stream. Porcupine accepts single channel, 16-bit PCM audio. The sample rate can be retrieved using pv_sample_rate(). Finally, Picovoice accepts input audio in consecutive chunks (aka frames) the length of each frame can be retrieved using pv_porcupine_frame_length().

extern const int16_t *get_next_audio_frame(void);

while (true) {
    const int16_t *pcm = get_next_audio_frame();
    int32_t keyword_index;
    const pv_status_t status = pv_porcupine_process(handle, pcm, &keyword_index);
    if (status != PV_STATUS_SUCCESS) {
        // error handling logic
    }
    if (keyword_index != -1) {
        // detection event logic/callback
    }
}

Finally, when done be sure to release the acquired resources.

pv_porcupine_delete(handle);

Releases

v3.0.0 - October 26th, 2023

  • Improvements to error reporting
  • Upgrades to authorization and authentication system
  • Various bug fixes and improvements
  • Added Farsi support for microcontrollers
  • Node min support bumped to 16
  • Unity editor min support bumped to 2021
  • Patches to .NET support

v2.2.0 - April 12th, 2023

  • Added language support for Arabic, Dutch, Hindi, Mandarin, Polish, Russian, Swedish and Vietnamese
  • Added support for .NET 7.0 and fixed support for .NET Standard 2.0
  • iOS minimum support moved to 11.0
  • Improved stability and performance

v2.1.0 - January 20th, 2022

  • Added macOS arm64 (Apple Silicon) support for Java and Unity SDKs
  • Various bug fixes and improvements

v2.0.0 - Nov 25th, 2021

  • Improved accuracy
  • Added Rust SDK
  • macOS arm64 support
  • Added NodeJS support for Windows, NVIDIA Jetson Nano, and BeagleBone
  • Added .NET support for NVIDIA Jetson Nano and BeagleBone
  • Runtime optimization

v1.9.0 - December 2nd, 2020

  • Added React Native SDK
  • Added Java SDK
  • Added .NET SDK
  • Added NodeJS SDK
  • Improved accuracy
  • Runtime optimization

v1.8.0 - May 27th, 2020

  • Improved accuracy
  • Runtime optimization

v1.7.0 - Feb 13th, 2020

  • Improved accuracy
  • Runtime optimization
  • Added support for Raspberry Pi 4
  • Added service-based Android demo application
  • Added C demo applications
  • Updated documentation

v1.6.0 - April 25th, 2019

  • Improved accuracy
  • Runtime optimization
  • Added support for BeagleBone
  • iOS build can run on simulator now

v1.5.0 - November 13, 2018

  • Improved accuracy
  • Runtime optimization
  • Added support for running within web browsers (WebAssembly)

v1.4.0 - July 20, 2018

  • Improved accuracy
  • Runtime optimizations.
  • Updated documentation

v1.3.0 - June 19, 2018

  • Improved accuracy
  • Runtime optimizations

v1.2.0 - April 21, 2018

  • Runtime optimizations

v1.1.0 - April 11, 2018

  • Added multiple command detection capability

v1.0.0 - March 13, 2018

  • Initial release

FAQ

You can find the FAQ here.

porcupine's People

Contributors

albho avatar amiranhari avatar bejager avatar csukuangfj avatar dbartle avatar dependabot[bot] avatar dimorphic avatar dyah10 avatar erismik avatar feliciatrinh avatar gdams avatar headhunterxamd avatar hellow554 avatar herlihalim avatar iamporus avatar ianb avatar iliadrm avatar itc-jalonso avatar jhoelzl avatar jtmuller5 avatar kenarsa avatar ksyeo1010 avatar laves avatar matthewscholefield avatar mehrdadfeller avatar mrrostam avatar oziee avatar soerson avatar stephenwithav avatar veeableful avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

porcupine's Issues

Making keyword issue on Linux

Expected behavior

Actual behavior

Steps to reproduce the behavior

Hi I am using Porcupine on Linux (Ubuntu 64-bit) for making a wake-up word "dayo". But I could not do that. I am getting error mesage like [ERROR] could not find the pronunciation for 'dayo'. If this is not a typo please contact [email protected].
Can you please add the word to Porcupine to make the word as wakeup keyword or can you suggest a procedure to create a custom wakeup word like I used above(dayo)?
The 'dayo' is pronounced as: https://www.howtopronounce.com/dayo/

Input overflow

Installing on Raspberry PI Zero W with Raspbian, demo runs for about 1-2 seconds and throws:

Traceback (most recent call last): File "demo/python/porcupine_demo.py", line 204, in <module> input_device_index=args.input_audio_device_index).run() File "demo/python/porcupine_demo.py", line 104, in run pcm = audio_stream.read(porcupine.frame_length) File "/usr/local/lib/python2.7/dist-packages/pyaudio.py", line 608, in read return pa.read_stream(self._stream, num_frames, exception_on_overflow) IOError: [Errno -9981] Input overflowed
Maybe I have to change the frame size? If so, where do I change parameters?

I tested using python demo/python/porcupine_demo.py --keyword_file_paths resources/keyword_files/alexa_raspberrypi.ppn --output_path ~/testporcupine.wav
it records the file for 2 seconds and stops. I can hear my voice fine in those 2 sec.

Python integrate error

I have problem with how to import porcupine to my python script. I had many problems with it, that i said that it could not import the library and so on, but that is fixed.

My code:
import sys
import soundfile
import os
import pyaudio

sys.path.append(r'E:/Desktop/Python/WakeWord/Porcupine/binding/python/')

from porcupine import Porcupine

library_path = 'Porcupine/lib/windows/amd64/libpv_porcupine.dll'
model_file_path = 'Porcupine/lib/common/porcupine_params.pv'
keyword_file_paths = 'Porcupine/resources/keyword_files/alexa_windows.ppn'
sensitivities = [0.5]
handle = Porcupine(library_path, model_file_path, keyword_file_paths=keyword_file_paths, sensitivities=sensitivities)

def get_next_audio_frame():
pass

while True:
pcm = get_next_audio_frame()
keyword_index = handle.process(pcm)
if keyword_index >= 0:
# detection event logic/callback
pass

And my error:
Traceback (most recent call last): File "program.py", line 15, in <module> handle = Porcupine(library_path, model_file_path, keyword_file_paths=keyword_file_paths, sensitivities=sensitivities) File "E:/Desktop/Python/WakeWord/Porcupine/binding/python\porcupine.py", line 84, in __init__ raise ValueError("Different number of sensitivity and keyword file path parameters are provided.") ValueError: Different number of sensitivity and keyword file path parameters are provided.

Cannot Create Wake Word for Raspberry Pi Using mac x86_64 binaries

Expected behavior

tools/optimizer/mac/x86_64/pv_porcupine_optimizer -r resources/ -w "ok google" -p raspberrypi -o .

outputs a .ppn file

Actual behavior

[WARN] This version of optimizer cannot create keyword files for raspberrypi. Please contact [email protected].

Steps to reproduce the behavior

$ tools/optimizer/mac/x86_64/pv_porcupine_optimizer -r resources/ -w "ok google" -p raspberrypi -o .

Please include the operating system and CPU architecture. When applicable, provide relevant audio data.

RPi

so we can't built models for Raspberry Pi ? we can only buy one for the RPi ?

Could not find the pronunciation

Hello
Thank you for the great work!

I have the following problem. When I run the following command:

tools\optimizer\windows\i686\pv_porcupine_optimizer -r resources/ -w cerner -p windows -o .

I get the following error:

[ERROR] Could not find the pronunciation for 'cerner'.

Is there a method to add this word to your vocabulary using the optimizer tool?

Thanks
Emins

Can't run the demo.

I tried to run the demo command like this:
python demo/python/porcupine_demo.py --keyword_file_paths resources/keyword_files/blueberry_windows.ppn

But i got this error:

Traceback (most recent call last):
  File "demo/python/porcupine_demo.py", line 204, in <module>
    input_device_index=args.input_audio_device_index).run()
  File "demo/python/porcupine_demo.py", line 92, in run
    sensitivities=[self._sensitivity] * num_keywords)
  File "demo/python\../../binding/python\porcupine.py", line 69, in __init__
    library = cdll.LoadLibrary(library_path)
  File "C:\Python\lib\ctypes\__init__.py", line 426, in LoadLibrary
    return self._dlltype(name)
  File "C:\Python\lib\ctypes\__init__.py", line 348, in __init__
    self._handle = _dlopen(self._name, mode)
OSError: [WinError 126] The specified module could not be found

What can i do to fix this problem

  • Fredrik

Visual Studio claims DLLs are invalid (both 32-bit and 64-bit)

I'm running Visual Studio 2017 on a Windows 10 machine.

I've tried this with both 32- and 64-bit projects.

The result I get is similar in each case:
4>..\..\porcupine\lib\libpv_porcupine.dll : fatal error LNK1107: invalid or corrupt file: cannot read at 0x430 (64-bit)
1>..\..\porcupine\lib\libpv_porcupine.dll : fatal error LNK1107: invalid or corrupt file: cannot read at 0x3F8 (32-bit)

I also tried previous committed versions with no luck.

Unable to create wake word using porcupine_optimizer

Hi,

Trying to build my custom wake word , for mac

I am running the following command :
./pv_porcupine_optimizer -r resources -w google -p mac -o ~/
./pv_porcupine_optimizer -r resources -w yellow -p mac -o ~/
./pv_porcupine_optimizer -r resources -w 'action item' -p mac -o ~/
./pv_porcupine_optimizer -r resources -w 'take note' -p mac -o ~/

getting the following:
[ERROR] Could not find a pronunciation for 'google'. If this is not a typo please contact [email protected].

Steps to reproduce the behavior

./pv_porcupine_optimizer -r resources -w google -p mac -o ~/

Increasing Porcupine verbosity level or reporting if currently in speech

TL;DR :

1) Is there any way to make Porcupine log more useful debugging info to LogCat in Android?

2) Does Porcupine internally detects beginning and end of speech in the audio data, similar to how PocketSphinx or Snowboy do this? And if it does, is there any way to get these states?

Issue description:

I'm currently integrating Porcupine into my Android app and the issue that I'm facing is that it doesn't detect anything.

Porcupine happily reports to logcat that it got initialized correctly with proper parameters:

06-19 19:08:21.378 11391-11808/ I/PORCUPINE: �[32m [INFO] model file path: /storage/emulated/0/Android/data/com.example.app/files/sync/porcupine/porcupine_params.pv�[0m
    �[32m [INFO] number of keywords: 1�[0m
    �[32m [INFO] keyword file path [0]: /storage/emulated/0/Android/data/com.example.app/files/sync/porcupine/models/alexa_android.ppn�[0m
    �[32m [INFO] sensitivity [0]: 0.500000�[0m

Sample rate and frame length were correctly set up in according to what porcupine requires using Porcupine#getFrameLength() and Porcupine#getSampleRate(). Porcupine does not show any errors about sample rate or frame length when I feed it audio data.

Keyword: Alexa (other available keywords)
OS: Android

PS: here's, to better illustrate idea from the 2nd quesiton, an example of how Snowboy reports if the any speech was detected in current audio frame (taken from here):

// Snowboy hotword detection.
int result = detector.RunDetection(audioData, audioData.length);

if (result == -2) {
   // post a higher CPU usage:
    // sendMessage(MsgEnum.MSG_VAD_NOSPEECH, null);
} else if (result == -1) {
    sendMessage(MsgEnum.MSG_ERROR, "Unknown Detection Error");
} else if (result == 0) {
     // post a higher CPU usage:
     // sendMessage(MsgEnum.MSG_VAD_SPEECH, null);
} else if (result > 0) {
     sendMessage(MsgEnum.MSG_ACTIVE, null);
     Log.i("Snowboy: ", "Hotword " + Integer.toString(result) + " detected!");
     player.start();
}

Thanks.

Python demo cannot run lib/linux/x86_64/libpv_porcupine.so on ChromeOS Linux

Expected behavior

python demo/python/porcupine_demo.py --keyword_file_paths resources/keyword_files/alexa_linux.ppn

Demo runs.

Actual behavior

Error:

Traceback (most recent call last):
  File "demo/python/porcupine_demo.py", line 210, in <module>
    input_device_index=args.input_audio_device_index).run()
  File "demo/python/porcupine_demo.py", line 95, in run
    sensitivities=[self._sensitivity] * num_keywords)
  File "demo/python/../../binding/python/porcupine.py", line 69, in __init__
    library = cdll.LoadLibrary(library_path)
  File "/usr/local/conda3/lib/python3.6/ctypes/__init__.py", line 426, in LoadLibrary
    return self._dlltype(name)
  File "/usr/local/conda3/lib/python3.6/ctypes/__init__.py", line 348, in __init__
    self._handle = _dlopen(self._name, mode)
OSError: demo/python/../../lib/linux/x86_64/libpv_porcupine.so: failed to map segment from shared object

Steps to reproduce the behavior

Environment:

ChromeOS on Acer CXI2
Linux localhost 3.14.0 #1 SMP PREEMPT Fri Jun 22 17:20:26 PDT 2018 x86_64 Intel(R) Core(TM) i7-5500U CPU @ 2.40GHz GenuineIntel GNU/Linux

Steps to reproduce:
Commented out soundfile dependency because libsndfile is not installed in the ChromeOS linux.
Start terminal with ChromeOS (Ctrl + Alt + T)
Clone Porcupine repo.
Installed portaudio, pyaudio.
Run python: python demo/python/porcupine_demo.py --keyword_file_paths resources/keyword_files/alexa_linux.ppn

I know ChromeOS Linux is not the typical use case. Looking for any guidance on where this error could stem from since failed to map segment from shared object is not specific for me.

C++ integration?

Hey, I wanted to use this in a c++ program, I can include the headers but have no idea how to link the dll.
I've tried to look how to link it using CMake for a couple of days now with no success.
I get
C:/Users/tatan/CLionProjects/TreeVoiceAssistant/HotwordDetection.cpp:27: undefined reference to pv_porcupine_process(pv_porcupine_object*, short const*, bool*)'`
every single time.
I'm using CLion as you can probably see, with MINGW and I can sucessfuly include the headers, but dlls just won't.

Please help

frame length

is the min frame length for porcupine 512??

using Python3.6 for testing

i have an audio file with a frame length of 256.. and when running porcupine.process on this it never picks up the hotword

the audio stream i am using is

ChunkID= b'RIFF'
TotalSize= 556
DataSize= 512
Format= b'WAVE'
SubChunk1ID= b'fmt '
SubChunk1Size= 16
AudioFormat= 1
NumChannels= 1
SampleRate= 16000
ByteRate= 32000
BlockAlign= 2
BitsPerSample= 16
SubChunk2ID= b'data'
SubChunk2Size= 512

detect multiple keywords concurrently

"Below is a quick demonstration of how to construct an instance of it to detect multiple keywords concurrently"

I'm a beginner in code, so I'm not sure how this works. Do I edit the python binding code? and when I call it in my command prompt do I still need the keyword_file_path header?

Porcupine crash observed when multiple porcupine instances(handles) are used with multiple threads for keyword detection in multiple audio channels

Hi Alireza,
We ran into a porcupine crash, when we tried creating multiple porcupine handles for processing multiple audio streams simultaneously.

Steps to reproduce:

  1. The C/C++ Application spawns two threads and creates two porcupine handles(handle1 and handle2) for detecting keywords from two audio steams.

  2. The first thread finishes detection for the first audio stream and frees the porcupine handle using the method pv_porcupine_delete(handle1);

  3. But the second thread still continues feeding audio data to porcupine engine from second audio stream using handle2.
    Here after the 3rd step, the application crashes with the following back-trace…

       #######
       6505== Invalid read of size 4
       6505==    at 0x40666A8: pv_sqrt (in /root/Arun/Porcupine-master/lib/linux/i386/libpv_porcupine.so)
       6505==    by 0x406439C: pv_specgram_compute (in /root/Arun/Porcupine-master/lib/linux/i386/libpv_porcupine.so)
       6505==    by 0x4063823: pv_mel_filter_bank_compute (in /root/Arun/Porcupine-master/lib/linux/i386/libpv_porcupine.so)
       ==6505==    by 0x40619C4: pv_porcupine_multiple_keywords_process (in /root/Arun/Porcupine-master/lib/linux/i386/libpv_porcupine.so)
       6505==    by 0x404AB38: start_thread (in /lib/libpthread-2.12.so)
       6505==    by 0x428ED6D: clone (in /lib/libc-2.12.so)
       ######
    

Please note, the above crash doesn’t occur, when the second thread creates its porcupine handle after the first thread finishes the execution.
Could you please have a look at this issue and let us know the root cause and resolution?

Regards,
Arun

Callback with audio frame containing wake word?

Is there a way to get the detected audio in the callback?
It would be really nice to have the callback include the audio frames so e.g. cloud-based wake word verification for the Alexa Voice Service can be used.

sensitivity 0.1 - 0.9 seems to have no difference

so i created a ppn file for mac x86_64
"hey janet"

even with the sensitivities set to [0.1] it picks up odd words when i say things like
"hey jant"
"hey jan Bert" (and i really make sure the Bert sound comes out strong)

i even tried setting the sen to [0.00001] and it still fires with odd sounds

i would have thought the sensitivity closer to 1 would false positive lots.. but even 0.001 it false positives with close sounding words.. but "jan BERT" really has a B sound which i would have expected with a low sensitivity to not accept

Logo design for Porcupine

I designed a logo for Porcupine. In this logo you can see simplicity and elegance more clearly. I used the letter P to indicate the real purpose. Even when we reduce it to size, it is so simple that there will be no distortion. I think it's a logo designed for you, I hope you like it.

1
2
3
4

1 object that is a NoneType

Error

I tried to first make a wake word. By using your optimizer, and it worked. And then I imported it. But this time it says that a object is a NoneType... I don't know what that means, but I google it and find out it maybe a empty variable. I don't know the cuase of this problem, so hope you guys know it. My code is this:

import os
import sys

sys.path.append(os.path.join(os.path.dirname(__file__), 'Porcupine/binding/python/'))

from porcupine import Porcupine

library_path = "Porcupine/lib/windows/amd64/libpv_porcupine.dll"
model_file_path = "Porcupine/lib/common/porcupine_params.pv"
keyword_file_paths = ['Porcupine/jarvis_windows.ppn']
sensitivities = [0.5]
handle = Porcupine(library_path, model_file_path, keyword_file_paths=keyword_file_paths, sensitivities=sensitivities)

def get_next_audio_frame():
    pass

while True:
    pcm = get_next_audio_frame()
    keyword_index = handle.process(pcm)
    if keyword_index >= 0:
        # detection event logic/callback
        pass

handle.delete()`

And the error im getting:
`Traceback (most recent call last):
  File "program.py", line 19, in <module>
    keyword_index = handle.process(pcm)
  File "Porcupine/binding/python\porcupine.py", line 154, in process
    status = self.process_func(self._handle, (c_short * len(pcm))(*pcm), byref(result))
TypeError: object of type 'NoneType' has no len()

I also gave you guys a picture of my file dir. So you can see where the files is.
desktop

Hope you guys can fix it... Just contact me over this issue, or via my email :)

  • Fredrik

New keyword

Can you add the keyword "lifetouch", thank you in advance. Great software.

[ERROR] Unable to resolve dependency for ':porcupinemanager@debug/compileClasspath': Could not resolve project :porcupine.

Expected behavior

I downloaded project .zip file from github, and tried to execute demo/andriod/app in Android Studio.
However, Gradle project sync failed.
Please help me!

Actual behavior

Error messages are below
Unable to resolve dependency for ':porcupinemanager@debug/compileClasspath': Could not resolve project :porcupine.
Unable to resolve dependency for ':porcupinemanager@debugAndroidTest/compileClasspath': Could not resolve project :porcupine.
Unable to resolve dependency for ':porcupinemanager@debugUnitTest/compileClasspath': Could not resolve project :porcupine.
Unable to resolve dependency for ':porcupinemanager@release/compileClasspath': Could not resolve project :porcupine.
Unable to resolve dependency for ':porcupinemanager@releaseUnitTest/compileClasspath': Could not resolve project :porcupine.

Steps to reproduce the behavior

download zip file and execute in Android Studio

Please include enough details so that the issue can reproduced independently by the resolver.

Install instructions needed

Expected behavior

Install instructions needed.

Actual behavior

none

Steps to reproduce the behavior

I want to install it on a RPI but cannot see any instructions on how to do so
Please include the operating system and CPU architecture. When applicable, provide relevant audio data.
RPI 3 B+ running debian stretch

Can't integrate Porcupine into python

I tried to integrate it into python but i got this error:

Traceback (most recent call last):
  File "SpeechRecognition.py", line 14, in <module>
    handle = Porcupine(library_path, model_file_path, keyword_file_paths=keyword_file_paths, sensitivities=sensitivities)
NameError: name 'Porcupine' is not defined

And this is my code:

# WAKE WORD
library_path = ['WakeWord/lib/${SYSTEM}/${MACHINE}/']
model_file_path = ['WakeWord/lib/common/porcupine_params.pv']
keyword_file_paths = ['WakeWord/resources/keyword_files/alexa_windows.ppn']
sensitivities = [0.5, 0.4]
handle = Porcupine(library_path, model_file_path, keyword_file_paths=keyword_file_paths, sensitivities=sensitivities)
# WAKE WORD END

def get_next_audio_frame():
    pass

while True:
    pcm = get_next_audio_frame()
    keyword_index = handle.process(pcm)
    if keyword_index >= 0:
        # detection event logic/callback
        pass

(Just the default from github)

  • Fredrik :)

How to run multiple wake word detection in Android

Hello,

In Python, we can do multiple wake word detection as documented below:

library_path = ... # Path to Porcupine's C library available under lib/${SYSTEM}/${MACHINE}/
model_file_path = ... # It is available at lib/common/porcupine_params.pv
keyword_file_paths = ['path/to/keyword/1', 'path/to/keyword/2', ...]
sensitivities = [0.5, 0.4, ...]
handle = Porcupine(library_path, model_file_path, keyword_file_paths=keyword_file_paths, sensitivities=sensitivities)

How do we do the same on Android? Can someone help?

[ERROR] loading parameter file failed with 'IO_ERROR' - Android

I'm trying to implement this library in Android.
Here's my code:
onCreate()

copyPorcupineConfigFiles(this);
        String keywordFilePath = new File(this.getFilesDir(), "francesca.ppn")
                .getAbsolutePath();
        String modelFilePath = new File(this.getFilesDir(), "params.pv").getAbsolutePath();
        try {
            manager = new PorcupineManager(modelFilePath, keywordFilePath, sensitivity, new KeywordCallback() {
                @Override
                public void run(int keyword_index) {
                    Toast.makeText(MainActivity.this, "Detected!", Toast.LENGTH_LONG).show();
                }
            });
            manager.start();
        } catch (PorcupineManagerException e) {
            e.printStackTrace();
        }

copyPorcupineConfigFiles()

private static void copyPorcupineConfigFiles(Context context) {
        int[] resIds = {R.raw.francesca, R.raw.params};
        Resources resources = context.getResources();
        for (int resId : resIds) {
            String filename = resources.getResourceEntryName(resId);
            String fileExtension = resId == R.raw.params ? ".pv" : ".ppn";
            InputStream is = null;
            OutputStream os = null;
            try {
                is = new BufferedInputStream(resources.openRawResource(resId),
                        256);
                os = new BufferedOutputStream(context.openFileOutput(filename + fileExtension,
                        Context.MODE_PRIVATE), 256);
                int r;
                while ((r = is.read()) != -1) {
                    os.write(r);
                }
                os.flush();
            } catch (IOException e) {
                Toast.makeText(context, "Error!", Toast.LENGTH_SHORT).show();
            } finally {
                try {
                    if (is != null) {
                        is.close();
                    }
                    if (os != null) {
                        os.close();
                    }
                } catch (IOException e) {
                    Toast.makeText(context, "Error!", Toast.LENGTH_SHORT).show();
                }
            }
        }
    }

keywordFilePath is /data/user/0/com.package.name/files/francesca.ppn
modelFilePath is /data/user/0/com.package.name/files/params.pv

Both paths are correct.

When I run, I get this Porcupine error:

07-30 17:36:51.343 18194-18194/? I/PORCUPINE: [ERROR] loading parameter file failed with 'IO_ERROR'
07-30 17:36:51.345 18194-18194/? W/System.err: ai.picovoice.porcupinemanager.PorcupineManagerException: ai.picovoice.porcupine.PorcupineException: java.io.IOException: Initialization of Porcupine failed.

Unable to run wake up word

Expected behavior

Actual behavior

I used this tutorial https://youtu.be/3z7LBW_Rl9c.

I have Ubuntu 16.04, Intel Core i3 7th Gen.
As a result of running service I got error.
Error log:
Traceback (most recent call last):
File "demo/python/porcupine_demo.py", line 207, in
input_device_index=args.input_audio_device_index).run()
File "demo/python/porcupine_demo.py", line 92, in run
sensitivities=[self._sensitivity] * num_keywords)
File "demo/python/../../binding/python/porcupine.py", line 114, in init
byref(self._handle))
File "/home/scale/.local/lib/python2.7/site-packages/enum.py", line 199, in init
raise EnumBadKeyError(key)
enum.EnumBadKeyError: Enumeration keys must be strings: 0

Pronunciation not found

Expected behavior

Train optimizer with "homie"

Actual behavior

[ERROR] could not find the pronunciation for 'homie'

Steps to reproduce the behavior

tools/optimizer/mac/x86_64/pv_porcupine_optimizer -r resources -w homie -p mac -o my_models

Please include enough details so that the issue can reproduced independently by the resolver.

Failed to Archive

Expected behavior

Archive without failing.

Actual behavior

When we Archive the build (iOS demo), it fails with the following error:
ld: bitcode bundle could not be generated because '/Users/userXXXX/Code/vivaa/native/Scribe/ios/Porcupine/watchos/libpv_porcupine.a(pv_porcupine.o)' was built without full bitcode. All object files and libraries for bitcode must be generated from Xcode Archive or Install build for architecture armv7k

Steps to reproduce the behavior

  1. Download Porcupine iOS Demo
  2. Product > Archive
  3. See error

Please include the operating system and CPU architecture. When applicable, provide relevant audio data.
Happens with iOS and watchOS demos.

Windows No positive results

Expected behavior

I expect to see a positive result when saying the wake word when running the demo on Windows.

Actual behavior

No result is reported.

Steps to reproduce the behavior

on a windows machine run:
python demo/python/porcupine_demo.py --keyword_file_paths alexa_windows.ppn

Please include the operating system and CPU architecture. When applicable, provide relevant audio data. Windows 10, Intel Core i7

Making keyword problem

Expected behavior

Actual behavior

Steps to reproduce the behavior

Please include the operating system and CPU architecture. When applicable, provide relevant audio data.

Hi, I'm making some prototype and try to make my keyword like below.
But it's not work with pronunciation error.
Can you suggest the way to resolve this problem or add a keyword "ariot" (not "a riot")??
Please advice about it.

Thanks.

C:\Users\1\Porcupine-master\Porcupine-master>tools\optimizer\windows\i686\pv_porcupine_optimizer.exe -r resources\ -w "ariot" -p windows -o .
[ERROR] could not find the pronunciation for 'ariot'. If this is not a typo please contact [email protected].

Can't create a new wake word

i tried creating a new wake word using the following command
tools/optimizer/mac/x86_64/pv_porcupine_optimizer -r resources -w “hello world” -p mac -o ~/Users/mahmoud/Desktop
when I use one word, example hello it gives the pronunciation error "tried many other words", when i use two or more i get
[ERROR] invalid arguments
the test file is working fine, but i can't add any other words.

any ideas?

OS: Mac OS high sierra (10.13.4)

Support for wake up sentences?

Hello,

First of all, thank you for this engine, it's awesome!

I've tried to create a small wake up sentence using the optimizer command line too, like the famous "ok google" but it seems not to be supported.

Command:

tools/optimizer/mac/x86_64/pv_porcupine_optimizer -r resources/ -w "ok test" -p mac -o ~/

Output:
[ERROR] Could not find a pronunciation for 'ok test'. If this is not a typo please contact [email protected].

On my real use case the trigger command will be "Ok + 2 small words"

Is this the expected behavior of Porcupine? Which means Porcupine is designed exclusively for single words detection? If so, any workaround?
Or did I miss something on the optimizer tool?

Thank you.

DLL for JNI Integration on non-linux machines?

As of now, I want to integrate Porcupine with Java through JNI, as you know this means that the dll must be built specifically for JNI Integration (through JNI Wrappers)

JNIEXPORT void JNICALL Java_package_name_ClassName_methodName(JNIEnv* env, jobject thiz) {}

I have only found this wrappers in android's .so libs, but because I want to implement it in Java, I cannot implement it on a Windows PC. I am using an AMD64 arch. Is there any way I can build this on my own? If not, could you provide me the modified dll?

iOS simulator binary

Expected behavior

When embedded for iOS project, it should be compilable for both deploying to device and simulator.

Actual behavior

It'll only compile if the target is to actual device.

Steps to reproduce the behavior

Compile the demo project on simulator, it will fail due to the binary was built only for device architecture.

I think it's probably worth it to provide a universal binary for iOS, otherwise it'll mean that adding this library to the project will cause that the project no longer compilable for simulator. The barrier of entry to adopt this library will be really high.

Initialization of Porcupine failed

ai.picovoice.porcupinemanager.PorcupineManagerException: ai.picovoice.porcupine.PorcupineException: java.lang.IllegalArgumentException: Initialization of Porcupine failed.

String keywordFilePath = new File(this.getFilesDir(), filename + ".ppn")
                .getAbsolutePath();
        String modelFilePath = new File(this.getFilesDir(), "params.pv").getAbsolutePath();
        try {
            manager = new PorcupineManager(modelFilePath, keywordFilePath, sensitivity, new KeywordCallback() {
                @Override
                public void run(int keyword_index) {
                    Toast.makeText(MainActivity.this, "Detected!", Toast.LENGTH_LONG).show();
                }
            });
            manager.start();
        } catch (PorcupineManagerException e) {
            e.printStackTrace();
            Log.e("Porcupine",e.getMessage());
        }

I have manually checked if keywordFilePath and modelFilePath are correct, and they are. This also happens in your demo application.

[ERROR] could not find the pronunciation of XXX

Hello!
I tried to use the optimizer with paired keywords like "ok" + the name of a french brand but without success. Typically, "OK " as a wake-word.

Is there any way to extend the pronunciation directory ? For example by providing audio data samples of french users saying this brand name?

Best,
Denis

optimizer for iOS fails

Expected behavior

A generated ppn file with the request keyword

Actual behavior

[WARN] This version of optimizer cannot create keyword files for ios. Please contact [email protected].

Steps to reproduce the behavior

tools/optimizer/mac/x86_64/pv_porcupine_optimizer -r resources/ -w "ok google" -p ios -o ~/

Running on macOS High Sierra 10.13.4

xcode linker error "Invalid bitcode signature"

Expected behavior

I'm trying to integrate Porcupine into an xcode project as per Porcupine/demo/ios/PorcupineDemo.
PorcupineDemo runs perfectly, so I copied the necessary components and settings of the demo to my project, but alas, it does not compile.

Actual behavior

Ld [~]/Library/Developer/Xcode/DerivedData/Porcupine_Test-bauzordzwumanjdyzvkejvhihxcl/Build/Products/Debug-iphonesimulator/Porcupine\ Test.app/Porcupine\ Test normal x86_64
    cd "[~]/Library/Autosave Information/Porcupine Test"

    export IPHONEOS_DEPLOYMENT_TARGET=11.3

    export PATH="/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin:/Applications/Xcode.app/Contents/Developer/usr/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin"

    /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang -arch x86_64 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator11.3.sdk -L[~]/Library/Developer/Xcode/DerivedData/Porcupine_Test-bauzordzwumanjdyzvkejvhihxcl/Build/Products/Debug-iphonesimulator -L[~]/Library/Autosave\ Information/Porcupine\ Test/lib/ios -F[~]/Library/Developer/Xcode/DerivedData/Porcupine_Test-bauzordzwumanjdyzvkejvhihxcl/Build/Products/Debug-iphonesimulator -filelist[~]/Library/Developer/Xcode/DerivedData/Porcupine_Test-bauzordzwumanjdyzvkejvhihxcl/Build/Intermediates.noindex/Porcupine\ Test.build/Debug-iphonesimulator/Porcupine\ Test.build/Objects-normal/x86_64/Porcupine\ Test.LinkFileList -Xlinker -rpath -Xlinker @executable_path/Frameworks -mios-simulator-version-min=11.3 -dead_strip -Xlinker -object_path_lto -Xlinker [~]/Library/Developer/Xcode/DerivedData/Porcupine_Test-bauzordzwumanjdyzvkejvhihxcl/Build/Intermediates.noindex/Porcupine\ Test.build/Debug-iphonesimulator/Porcupine\ Test.build/Objects-normal/x86_64/Porcupine\ Test_lto.o -Xlinker -export_dynamic -Xlinker -no_deduplicate -Xlinker -objc_abi_version -Xlinker 2 -fobjc-link-runtime -L/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/iphonesimulator -Xlinker -add_ast_path -Xlinker [~]/Library/Developer/Xcode/DerivedData/Porcupine_Test-bauzordzwumanjdyzvkejvhihxcl/Build/Intermediates.noindex/Porcupine\ Test.build/Debug-iphonesimulator/Porcupine\ Test.build/Objects-normal/x86_64/Porcupine_Test.swiftmodule -Xlinker -sectcreate -Xlinker __TEXT -Xlinker __entitlements -Xlinker [~]/Library/Developer/Xcode/DerivedData/Porcupine_Test-bauzordzwumanjdyzvkejvhihxcl/Build/Intermediates.noindex/Porcupine\ Test.build/Debug-iphonesimulator/Porcupine\ Test.build/Porcupine\ Test.app-Simulated.xcent -lpv_porcupine -Xlinker -dependency_info -Xlinker [~]/Library/Developer/Xcode/DerivedData/Porcupine_Test-bauzordzwumanjdyzvkejvhihxcl/Build/Intermediates.noindex/Porcupine\ Test.build/Debug-iphonesimulator/Porcupine\ Test.build/Objects-normal/x86_64/Porcupine\ Test_dependency_info.dat -o [~]/Library/Developer/Xcode/DerivedData/Porcupine_Test-bauzordzwumanjdyzvkejvhihxcl/Build/Products/Debug-iphonesimulator/Porcupine\ Test.app/Porcupine\ Test

error: Invalid bitcode signature
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Steps to reproduce the behavior

I) create new xcode project named 'Porcupine Test'
II) copy

  1. Porcupine/include to ${PROJECT_DIR}/include

  2. Porcupine/lib to ${PROJECT_DIR}/lib

  3. Porcupine/binding/ios/PorcupineManager to ${PROJECT_DIR}/Porcupine Test/PorcupineManager

  4. Porcupine/demo/ios/PorcupineDemo/module.modulemap to ${PROJECT_DIR}/Porcupine Test/Porcupine/module.modulemap

    a) edit module.modulemap relative paths to '../../include'

III) set Build Settings

  1. Search Paths -> Library Search Paths to ${PROJECT_DIR}/lib/ios

  2. Swift Compiler - Search Paths -> Import Paths to ${PROJECT_DIR}/Porcupine\ Test/Porcupine

IV) add ${PROJECT_DIR}/lib/ios/libpv_porcupine.a to Build Phases -> Link Binary With Libraries

V) build project

xcode 9.3 (9E145)
macos 10.13.4
1.6 GHz Intel Core i5

python demo crashed

Expected behavior

The python demo keeps running until I quit it.

Actual behavior

The demo crashed with following error:

Traceback (most recent call last):
  File "demo/python/porcupine_demo.py", line 207, in <module>
    input_device_index=args.input_audio_device_index).run()
  File "demo/python/porcupine_demo.py", line 104, in run
    pcm = audio_stream.read(porcupine.frame_length)
  File "/usr/lib/python2.7/dist-packages/pyaudio.py", line 608, in read
    return pa.read_stream(self._stream, num_frames, exception_on_overflow)
IOError: [Errno -9981] Input overflowed

Steps to reproduce the behavior

Start the demo on a Rasperry PI Zero with ReSpeaker 2-Mic-HAT with following settings:

python demo/python/porcupine_demo.py --keyword_file_paths ./resources/keyword_files/grasshopper_raspberrypi.ppn --library_path ./lib/raspberry-pi/arm11/libpv_porcupine.so --input_audio_device_index 2

OS is Raspbian Stretch Lite.

pronunciation not found

Hi, and thanks for your great product

My problem is that When i try to run
tools/optimizer/mac/x86_64/pv_porcupine_optimizer -r resources/ -p mac -o . -w "hey rimon"
I will get the following error:
[ERROR] could not find the pronunciation for 'hey rimon'
When I've read the docs, it was mentioned that only the words in english are supported.
I wanted to know is there anyway that I can add the pronunciation to the dictionary so I will be able to get my costume keyword wake up model?
Thanks

missing wake word

HI,

[ERROR] could not find the pronunciation for 'trello'.

Is it possible to add this word to the dictionary?

Can't compile the iOS demo build

I tried to compile the iOS demo, but i am getting errors while compiling
Error is:
Undefined symbols for architecture x86_64:
"_pv_porcupine_delete", referenced from:
PorcupineDemo.PorcupineManager.stop() -> () in PorcupineManager.o
"_pv_sample_rate", referenced from:
PorcupineDemo.PorcupineManager.start() throws -> () in PorcupineManager.o
"_pv_porcupine_frame_length", referenced from:
PorcupineDemo.PorcupineManager.start() throws -> () in PorcupineManager.o
"_pv_porcupine_multiple_keywords_init", referenced from:
PorcupineDemo.PorcupineManager.start() throws -> () in PorcupineManager.o
"_pv_porcupine_multiple_keywords_process", referenced from:
closure #1 (Swift.UnsafeMutableRawPointer?, Swift.OpaquePointer, Swift.UnsafeMutablePointer<__C.AudioQueueBuffer>, Swift.UnsafePointer<__C.AudioTimeStamp>, Swift.UInt32, Swift.UnsafePointer<__C.AudioStreamPacketDescription>?) -> () in variable initialization expression of PorcupineDemo.PorcupineManager.(audioCallback in _BEC5063E4C49B2A2811E8F4D93649EFF) : @convention(c) (Swift.UnsafeMutableRawPointer?, Swift.OpaquePointer, Swift.UnsafeMutablePointer<__C.AudioQueueBuffer>, Swift.UnsafePointer<__C.AudioTimeStamp>, Swift.UInt32, Swift.UnsafePointer<__C.AudioStreamPacketDescription>?) -> () in PorcupineManager.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Can you please help me to compile the demo build

Android library does not support native C linking

Expected behavior

Use porcupine in C/C++ Android NDK native program.

Actual behavior

"undefined reference" to every porcupine function.

Steps to reproduce the behavior

Write a C program;
include porcupine C headers;
call API C functions;
link against libpv_porcupine.so found in android arm_v7a folder;
build with android NDK v15c.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.