Porcupine
Wake Word

production-ready models, trained in seconds, can run anywhere

Start Building
Talk to Sales

Private

All voice data is processed on-device. Intrinsically HIPAA and GDPR compliant.

Zero-Latency

Edge-first architecture eliminates unpredictable network delay.

Reliable

100% of the voice recognition is on-device. No concurrency limit. No downtime.

Free Tier

Train custom models, build, and deploy for free. No credit card required.

Self Service

Train custom models within seconds using Picovoice Console.

Cross Platform

Runs everywhere. Linux, macOS, Windows, Android, iOS, Raspberry Pi, NVIDIA Jetson Nano, BeagleBone, Arm Cortex-M, and modern web browsers are supported.

Try it!
Arrow (pointing at microphone button)
Press the microphone button to activate the demo
Porcupine porcupine = Porcupine.FromKeywordPaths(
"${ACCESS_KEY}",
new List<string>{"${KEYWORD_PATH}"});
while (true)
{
var keywordIndex = porcupine.Process(AudioFrame());
if (keywordIndex >= 0)
{ ... }
}
Build with .NET
PorcupineManager porcupineManager = new PorcupineManager.Builder()
.setAccessKey("${ACCESS_KEY}")
.setKeywordPath("${KEYWORD_PATH}")
.build(context,
new PorcupineManagerCallback() {
@Override
public void invoke(int keywordIndex) { ... }
});
porcupineManager.start()
Build with Android
constructor(private porcupineService: PorcupineService) {
this.keywordInsert detection = porcupineService.keyword$.subscribe(
keywordLabel => { ... })
}
async ngOnInit() {
await this.porcupineService.init(
PorcupineWorkerFactory,
{
accessKey: "${ACCESS_KEY}",
keywords: { ... }
}
)
}
Build with Angular
pv_porcupine_t *porcupine = NULL;
pv_porcupine_init(
"${ACCESS_KEY}"
"${MODEL_PATH}",
1,
&"${KEYWORD_PATH}",
&sensitivity,
&porcupine);
while (true) {
pv_porcupine_process(
porcupine,
audio_frame(),
&keyword_index);
if (keyword_index >= 0) { ... }
}
Build with C
PorcupineManager porcupineManager = await PorcupineManager.fromKeywordPaths(
"${ACCESS_KEY}",
["${KEYWORD_PATH}"],
(keywordIndex) => { ... });
await porcupineManager.start()
Build with Flutter
porcupine := Porcupine{
AccessKey: "${ACCESS_KEY}",
KeywordPaths: []string{"${KEYWORD_PATH}"}}
porcupine.Init()
for {
keywordIndex, err := porcupine.Process(audioFrame())
if keywordIndex >= 0 { ... }
}
Build with Go
let porcupineManager = try PorcupineManager(
"${ACCESS_KEY}",
keywordPath: "${KEYWORD_PATH}",
onDetection: { keywordIndex in ... })
try porcupineManager.start()
Build with iOS
Porcupine porcupine = new Porcupine.Builder()
.setAccessKey("${ACCESS_KEY}")
.setKeywordPath("${KEYWORD_PATH}")
.build();
while (true) {
int keywordIndex = porcupine.process(audioFrame());
if (keywordIndex >= 0) { ... }
}
Build with Java
let porcupine = new Porcupine(
"${ACCESS_KEY}",
["${KEYWORD_PATH}"],
[sensitivity]);
while (true) {
let keywordIndex = porcupine.process(audioFrame());
if (keywordIndex >= 0) { ... }
}
Build with NodeJS
porcupine = pvporcupine.create(
accessKey="${ACCESS_KEY}",
keyword_paths=['${KEYWORD_PATH}'])
while True:
keyword_index = porcupine.process(audio_frame())
if keyword_index >= 0:
...
Build with Python
const {
isLoaded,
isListening,
isError,
resume,
pause
} = usePorcupine(
PorcupineWorkerFactory,
{
accessKey: "${ACCESS_KEY}",
keywords: [{ ... }]
},
(keywordLabel: string) => { ... };
);
Build with React
let porcupineMananger = await PorcupineManager.fromKeywordPaths(
"${ACCESS_KEY}",
["${KEYWORD_PATH}"],
(keywordIndex) => { ... });
await porcupineMananger.start()
Build with React Native
PorcupineManager porcupineManager = PorcupineManager.FromKeywordPaths(
"${ACCESS_KEY}",
new List<string>{"${KEYWORD_PATH}"},
(keywordIndex) => { ... });
porcupineManager.start();
Build with Unity
<Porcupine
ref="porcupine"
v-bind:porcupineFactoryArgs="{
accessKey: '${ACCESS_KEY}',
keywords: [{ ... }]
}"
v-bind:porcupineFactory="factory"
v-on:ppn-ready="ppnReadyFn"
v-on:ppn-keyword="ppnKeywordFn"
/>
methods: {
ppnKeywordFn: function (keywordLabel) { ... }
}
Build with Vue

English

German
Deutsch

French
Français

Spanish
Español

Japanese
日本語

Korean
한국어

Portuguese
Português

Italian
Italiano