Made in Vancouver, Canada by Picovoice
Eagle is an on-device speaker recognition engine. Eagle is:
- Private; All voice processing runs locally.
- Accurate
- Language-agnostic and text-independent
- Optimized for real-time processing
- Cross-Platform:
- Linux (x86_64), macOS (x86_64, arm64), Windows (x86_64, arm64)
- Android and iOS
- Chrome, Safari, Firefox, and Edge
- Raspberry Pi (3, 4, 5)
Eagle consists of two distinct steps: Enrollment and Recognition. In the enrollment step, Eagle analyzes a series of
utterances from a particular speaker to learn their unique voiceprint. This step results in a Profile,
which can be stored and utilized in the next step. During the Recognition step, Eagle registers speakers using
the Profiles generated in the enrollment phase. Then, Eagle compares the incoming frames of audio to the voiceprints
of all enrolled speakers in real-time to determine the similarity between them.
AccessKey is your authentication and authorization token for deploying Picovoice SDKs, including Eagle. Anyone who is using Picovoice needs to have a valid AccessKey. You must keep your AccessKey secret. You would need internet connectivity to validate your AccessKey with Picovoice license servers even though the speaker recognition is running 100% offline.
AccessKey also verifies that your usage is within the limits of your account. You can see your usage limits and real-time usage on your Picovoice Console Profile. To continue using Picovoice after your trial or renew and adjust your usage limits, please reach out to our Enterprise Sales Team or your existing Picovoice contact.
Install the demo package:
pip3 install pveagledemoCreate a new speaker profile:
eagle_demo_mic enroll --access_key ${ACCESS_KEY} --output_profile_path ${OUTPUT_PROFILE_PATH}or
eagle_demo_file enroll \
--access_key ${ACCESS_KEY} \
--enroll_audio_paths ${ENROLL_AUDIO_PATHS}
--output_profile_path ${OUTPUT_PROFILE_PATH}Test the speaker recognition engine:
eagle_demo_mic test \
--access_key ${ACCESS_KEY} \
--input_profile_paths ${INPUT_PROFILE_PATH}or
eagle_demo_file test \
--access_key ${ACCESS_KEY} \
--input_profile_paths ${INPUT_PROFILE_PATH}
--test_audio_paths ${TEST_AUDIO_PATHS}Replace ${ACCESS_KEY} with yours obtained from Picovoice Console.
For more information about Python demos go to demo/python.
Using Android Studio, open demo/android/EagleDemo as an Android project and then run the application.
Open the file MainActivity.java and replace "${YOUR_ACCESS_KEY_HERE}" in with your AccessKey.
To run the demo, go to demo/ios/EagleDemo and run:
pod installReplace let accessKey = "${YOUR_ACCESS_KEY_HERE}" in the file ViewModel.swift with your AccessKey.
Then, using Xcode, open the generated EagleDemo.xcworkspace and run the application.
Build the demo:
cmake -S demo/c/ -B demo/c/build && cmake --build demo/c/build --target eagle_demo_micTo list the available audio input devices:
./demo/c/build/eagle_demo_mic -sTo enroll a new speaker:
./demo/c/build/eagle_demo_mic -l ${LIBRARY_PATH} -m ${MODEL_PATH} -a ${ACCESS_KEY} -e ${OUTPUT_PROFILE_PATH}To test the speaker recognition engine:
./demo/c/build/eagle_demo_mic -l ${LIBRARY_PATH} -m ${MODEL_PATH} -a ${ACCESS_KEY} -i ${INPUT_PROFILE_PATH}Replace ${LIBRARY_PATH} with path to appropriate library available under lib, ${MODEL_PATH} with path
to the model file available under lib/common, ${ACCESS_KEY} with AccessKey
obtained from Picovoice Console. ${OUTPUT_PROFILE_PATH} in the enrollment step is the
path to the generated speaker profile. ${INPUT_PROFILE_PATH} in the recognition step is the path to the generated
speaker
profile to be tested.
For more information about C demos go to demo/c.
From demo/web run the following in the terminal:
yarn
yarn start(or)
npm install
npm run startOpen http://localhost:5000 in your browser to try the demo.
Install the demo package:
npm install -g @picovoice/eagle-node-demoCreate a new speaker profile:
eagle-mic-demo --enroll \
--access_key ${ACCESS_KEY} \
--output_profile_path ${OUTPUT_PROFILE_PATH}or
eagle-file-demo --enroll \
--access_key ${ACCESS_KEY} \
--enroll_audio_paths ${ENROLL_AUDIO_PATH_1 ...} \
--output_profile_path ${OUTPUT_PROFILE_PATH}Test the speaker recognition engine:
eagle-mic-demo --test \
--access_key ${ACCESS_KEY} \
--input_profile_paths ${INPUT_PROFILE_PATH_1 ...}or
eagle-file-demo --test \
--access_key ${ACCESS_KEY} \
--test_audio_path ${TEST_AUDIO_PATH} \
--input_profile_paths ${INPUT_PROFILE_PATH_1 ...}Replace ${ACCESS_KEY} with yours obtained from Picovoice Console.
For more information about Node.js demos go to demo/nodejs.
Install the Python SDK:
pip3 install pveagleCreate an instance of the profiler:
import pveagle
# AccessKey obtained from Picovoice Console (https://console.picovoice.ai/)
access_key = "${ACCESS_KEY}"
eagle_profiler = pveagle.create_profiler(access_key)Create a new speaker profile:
def get_next_enroll_audio_frame(frame_length):
pass
def has_next_enroll_audio_frame(frame_length):
pass
percentage = 0.0
while percentage < 100.0 and has_next_enroll_audio_frame(eagle_profiler.frame_length):
percentage = eagle_profiler.enroll(get_next_enroll_audio_frame(eagle_profiler.frame_length))
percentage = eagle_profiler.flush()Export the speaker profile once enrollment is complete:
speaker_profile = eagle_profiler.export()Release the resources acquired by the profiler:
eagle_profiler.delete()Create an instance of the engine:
eagle = pveagle.create_recognizer(access_key, speaker_profile)Process audio with one or more speaker profiles from the EagleProfiler.
def get_next_audio_chunk(num_samples):
pass
while True:
scores = eagle.process(get_next_audio_chunk(eagle.min_process_samples), speaker_profiles)Finally, when done be sure to explicitly release the resources:
eagle.delete()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:eagle-android:${LATEST_VERSION}'
}Create an instance of the profiler:
import ai.picovoice.eagle.*;
final String accessKey = "${ACCESS_KEY}";
try {
EagleProfiler eagleProfiler = new EagleProfiler.Builder()
.setAccessKey(accessKey)
.build();
} catch (EagleException e) { }Create a new speaker profile:
public short[] getNextAudioFrame() {
// get audio frame
}
EagleProfilerEnrollResult result = null;
try {
while (result != null && result.getPercentage() < 100.0) {
result = eagleProfiler.enroll(getNextAudioFrame());
}
} catch (EagleException e) { }Export the speaker profile once enrollment is complete:
try {
EagleProfile speakerProfile = eagleProfiler.export();
} catch (EagleException e) { }Release the resources acquired by the profiler:
eagleProfiler.delete();Create an instance of the engine:
import ai.picovoice.eagle.*;
final String accessKey = "${ACCESS_KEY}";
try {
Eagle eagle = new Eagle.Builder()
.setAccessKey(accessKey)
.build();
} catch (EagleException e) { }Process incoming audio frames:
public short[] getNextProcessAudioData() {
// get audio sample
}
try {
EagleProfile[] speakerProfiles = {speakerProfile};
while (true) {
float[] scores = eagle.process(getNextProcessAudioData(), speakerProfiles);
}
} catch (EagleException e) { }Finally, when done be sure to explicitly release the resources:
eagle.delete()The Eagle iOS binding is available via CocoaPods. To import it into your iOS project, add the following line to your Podfile and run pod install:
pod 'Eagle-iOS'Create an instance of the profiler:
import pveagle
let accessKey : String = // .. AccessKey obtained from Picovoice Console (https://console.picovoice.ai/)
let eagleProfiler = try EagleProfiler(accessKey: accessKey)Create a new speaker profile:
func get_next_audio_frame(frameLength: Int) -> [Int16] {
// ...
}
do {
var percentage = 0.0
while (percentage < 100.0) {
percentage = try eagleProfiler.enroll(pcm: get_next_audio_frame())
}
} catch { }Export the speaker profile once enrollment is complete:
let speakerProfile = try eagleProfiler.export()Release the resources acquired by the profiler:
eagleProfiler.delete()Create an instance of the engine:
let eagle = Eagle(accessKey: accessKey)Process incoming audio frames using the speaker profile exported before:
func get_next_process_audio_data(numSamples: Int) -> [Int16] {
// ...
}
do {
let profileScores = try eagle.process(pcm: get_next_process_audio_data(eagle.minProcessSamples()), speakerProfiles: [speakerProfile])
} catch { }Finally, when done be sure to explicitly release the resources:
eagle.delete()include/pv_eagle.h header file contains relevant information.
Build an instance of the profiler:
const char *access_key = "${ACCESS_KEY}";
const char *model_path = "${MODEL_PATH}";
const char *device = "best";
const int32_t min_enrollment_chunks = 1;
const float voice_threshold = 0.3f;
pv_eagle_profiler_t *eagle_profiler = NULL;
pv_status_t status = pv_eagle_profiler_init(
access_key,
model_path,
device,
min_enrollment_chunks,
voice_threshold,
&eagle_profiler);
if (status != PV_STATUS_SUCCESS) {
// error handling logic
}Replace ${ACCESS_KEY} with the AccessKey obtained from Picovoice Console, and ${MODEL_PATH} with the path to the
model file available under lib/common.
Use eagle_profiler to create a new speaker profile:
extern const int16_t *get_next_enroll_audio_frame(int32_t frame_length);
extern const bool has_next_enroll_audio_frame(int32_t frame_length);
const int32_t frame_length = pv_eagle_profiler_frame_length();
float enroll_percentage = 0.0f;
while (enroll_percentage < 100.0f && has_next_enroll_audio_frame(frame_length)) {
status = pv_eagle_profiler_enroll(
eagle_profiler,
get_next_enroll_audio_frame(frame_length),
&enroll_percentage);
if (status != PV_STATUS_SUCCESS) {
// error handling logic
}
}
status = pv_eagle_profiler_flush(
eagle_profiler,
&enroll_percentage);
if (status != PV_STATUS_SUCCESS) {
// error handling logic
}
int32_t profile_size_bytes = 0;
status = pv_eagle_profiler_export_size(eagle_profiler, &profile_size_bytes);
void *speaker_profile = malloc(profile_size_bytes);
status = pv_eagle_profiler_export(
eagle_profiler,
speaker_profile);
if (status != PV_STATUS_SUCCESS) {
// error handling logic
}Once the speaker profile is exported, the resources acquired by the profiler can be released:
pv_eagle_profiler_delete(eagle_profiler);Create an instance of the engine:
pv_eagle_t *eagle = NULL;
pv_status_t status = pv_eagle_init(
access_key,
model_path,
device,
voice_threshold,
&eagle);
if (status != PV_STATUS_SUCCESS) {
// error handling logic
}Now the eagle can be used to process incoming audio frames using the speaker profile exported before:
extern const int16_t *get_next_audio_frame(void);
extern const int32_t get_next_audio_num_samples(void);
float *scores = NULL;
while (true) {
const int16_t *pcm = ;
const pv_status_t status = pv_eagle_process(
eagle,
get_next_audio_frame(),
get_next_audio_num_samples(),
&speaker_profile,
1,
&scores);
if (status != PV_STATUS_SUCCESS) {
// error handling logic
}
}Finally, when done be sure to release the acquired resources:
pv_eagle_scores_delete(scores);
pv_eagle_delete(handle);Install the Eagle package with yarn (or npm):
yarn add @picovoice/eagle-webCreate an instance of the EagleProfiler:
const eagleModel = {
publicPath: ${MODEL_RELATIVE_PATH},
// or
base64: ${MODEL_BASE64_STRING},
}
const eagleProfiler = await EagleProfiler.create(
${ACCESS_KEY},
eagleModel);Replace ${ACCESS_KEY} with the AccessKey obtained from Picovoice Console, and the model options with the path to the
model file available under lib/common or a base64 string of it.
Use EagleProfiler to create a new speaker profile:
function getAudioData(numSamples): Int16Array {
// get audio frame of size `numSamples`
}
let percentage = 0;
while (percentage < 100) {
const audioData = getAudioData(eagleProfiler.minEnrollSamples);
const result: EagleProfilerEnrollResult = await eagleProfiler.enroll(audioData);
if (result.feedback === EagleProfilerEnrollFeedback.AUDIO_OK) {
// audio is good!
} else {
// feedback code will tell you why audio was not used in enrollment
}
percentage = result.percentage;
}
// export speaker profile
const speakerProfile: EagleProfile = eagleProfiler.export();Create an instance of the engine with one or more speaker profiles created by the EagleProfiler:
const eagle = await Eagle.create(
${ACCESS_KEY},
eagleModel,
speakerProfile);Process audio frames and get speaker scores (i.e. likelihood they are speaking) in real-time:
function getAudioData(numSamples): Int16Array {
// get audio frame of size `numSamples`
}
while (true) {
const audioData = getAudioData(eagle.frameLength);
const scores: number[] = await eagle.process(audioData);
}Install Node.js SDK:
yarn add @picovoice/eagle-nodeCreate an instance of the profiler:
const { EagleProfiler } = require("@picovoice/eagle-node");
const accessKey = "${ACCESS_KEY}"; // Obtained from the Picovoice Console (https://console.picovoice.ai/)
const eagleProfiler = new EagleProfiler(accessKey);Create a new speaker profile:
function getAudioData(numSamples): Int16Array {
// get audio frame of size `numSamples`
}
function hasAudioData(numSamples): Boolean {
// check if there are any remaining samples in the stream
}
let percentage = 0;
while (percentage < 100 && hasAudioData(eagleProfiler.frameLength)) {
const audioData = getAudioData(eagleProfiler.frameLength);
percentage = eagleProfiler.enroll(audioData);
}
percentage = eagleProfiler.flush();Export the speaker profile once enrollment is complete:
const speakerProfile: Uint8Array = eagleProfiler.export();Release the resources acquired by the profiler:
eagleProfiler.release();Create an instance of the engine:
const { Eagle } = require("@picovoice/eagle-node");
const accessKey = "${ACCESS_KEY}"; // Obtained from the Picovoice Console (https://console.picovoice.ai/)
const eagle = new Eagle(accessKey);Process audio with one or more speaker profiles from the EagleProfiler:
function getAudioData(numSamples): Int16Array {
// get audio frame of size `numSamples`
}
while (true) {
const audioData = getAudioData(eagle.minProcessSamples);
const scores: number[] | null = await eagle.process(
audioData.
speakerProfile
);
if (scores) {
// do something with the scores
}
}Finally, when done be sure to explicitly release the resources:
eagle.release()- Improved engine performance
- Improved the enrollment and recognition process
- Improved engine performance
- Added support for running on GPU or multiple CPU cores
- Node.js min version bumped to Node 18
- iOS min version bumped to iOS 16
- Enhanced engine accuracy
- Improved the enrollment process
- Added Raspberry Pi 5 support
- Various bug fixes and improvements
- Improvements to error reporting
- Upgrades to authorization and authentication system
- Various bug fixes and improvements
- Web min support bumped to Node 16
- iOS support bumped to iOS 13
- Beta release
You can find the FAQ here.