OK Google, Add Hotword Detection to Chrome
Tags: 100daysofcode, challenge, webdev, webassembly
Published: 2023-02-03 16:58:45

Today is day 25 and we'll learn how to add hotword detection to web browsers with [Porcupine Wake Word](https://picovoice.ai/platform/porcupine/) [Web SDK](https://picovoice.ai/docs/quick-start/porcupine-web/).

**Setup the Project**
Initialize an NPM project:
```
npm init
```
Install the dependencies:
```
npm install @picovoice/web-voice-processor @picovoice/porcupine-web
```
Install http-server as a development dependency:
```
npm install http-server --save-dev
```
Download [Porcupine](https://github.com/Picovoice/porcupine/raw/master/lib/common/porcupine_params.pv) (i.e. Deep Neural Network). 
Run the following to turn the binary model into a base64 string, from the project folder. 
```
npx pvbase64 -i ${DOWNLOADED_MODEL_PATH} -o porcupine_params.js
```
Don't forget to replace ${DOWNLOADED_MODEL_PATH} with yours (e.g. ~/Downloads/porcupine_params.pv).
Create a boilerplate HTML file called index.html with the content below:

```
<!DOCTYPE html>
<html lang="en">
<head>
  <script src=
    "node_modules/@picovoice/web-voice-processor/dist/iife/index.js">
  </script>
  <script src=
    "node_modules/@picovoice/porcupine-web/dist/iife/index.js">
  </script>
  <script src="porcupine_params.js"></script>
</head>
<body>
<h1>Porcupine Web Demo</h1>
</body>
</html>
```
Run the local server to load the page:
```
yarn run http-server -a localhost -p 5000
```
Check the page at http://localhost:5000.

**Train "OK Google"**

1. Sign up for [Picovoice Console](https://console.picovoice.ai/) for free
2. Go to the [Porcupine Page](https://console.picovoice.ai/ppn).
3. Select English as the language for your model.
4. Type in "OK Google" and click on the train button.
5. Select Web (WASM) as the platform and click on Download. 
6. Unzip the .zip file (which is probably in your download folder now.) You see a file with the suffix .ppn. That's the hotword model. Transform it into a base64 string. 

```
npx pvbase64 \
-i ${DOWNLOADED_PPN_PATH} \
-o ok_google.js \
-n OK_GOOGLE_KEYWORD_MODEL
```
**Wire it up**
1. Copy your AccessKey from Picovoice Console.
2. Add the base64 keyword model as a script:
```<script src="ok_google.js"></script>```
3. Add div elements for debugging and showing the result:
```
<div id="status"></div>
<div id="result"></div>
```
4. Initialize Porcupine. Don't forget to replace ${ACCESS_KEY} with yours.
```
<script type="application/javascript">
function porcupineErrorCallback(error) {
  console.log(error);
  document.getElementById("status").innerHTML = error;
}
function porcupineKeywordCallback(detection) {
  const time = new Date();
  const message = `Detection at ${time.toLocaleTimeString()}`
  console.log(message);
  document.getElementById("result").innerHTML = message;
}

async function startPorcupine() {
  try {
    let porcupine = await PorcupineWeb.PorcupineWorker.create(
      ${ACCESS_KEY},
      [{label: "OK Google", base64: OK_GOOGLE_KEYWORD_MODEL}],
      porcupineKeywordCallback,
      {base64: modelParams},
    );
    await window.WebVoiceProcessor.
      WebVoiceProcessor.subscribe(porcupine);
  } catch (err) {
    porcupineErrorCallback(err);
  }
}
</script>
```