Day 12: Always Listening Voice Commands with React.js
Tags: 100daysofcode, challenge, react, webdev
Published: 2023-01-17 17:24:22

Wake words are the most-known example for always listening commands. Echo smart speakers and iPhones always listen for the wake words Alexa and Hey Siri to activate the software for listen to further voice commands. 

Always listening commands are not limited to wake words. Airlines can add always listening commands such as "Book a Flight" or "Check in" directly to their websites instead of starting with "Hey Airline X". 

**Setup the Project**
1. Create:
```
npx create-react-app porcupine-react

```
2. Install:
```
npm install @picovoice/porcupine-react @picovoice/web-voice-processor
```
3. Download:
Run the following from the project folder to turn the binary model into a base64 string. Don't forget to replace `${DOWNLOADED_MODEL_PATH}` with yours (e.g. `~/Downloads/porcupine_params.pv`).
```
npx pvbase64 -i ${DOWNLOADED_MODEL_PATH} -o src/porcupine_params.js
```
4. Run
```
yarn start
```
**Train Wake Word Models**
1. Sign up for [Picovoice Console](https://console.picovoice.ai/)
2. Visit `Porcupine Page` on Picovoice Console
3. Select `English`
4. Type in `Hey Jarvis` or the phrase you want.
5. Test it out on your browser.
6. When you are happy, click on the train button.
7. Select `Web (WASM)` as the platform.
8. Click on Download. A `.zip` file will be downloaded.
9. Once you unzip, inside the folder, you see a `.ppn` a file. That's your speech model! Transform it into a `base64` string. Don't forget to replace `${DOWNLOADED_PPN_PATH}` with the path to downloaded file (e.g. `~/Downloads/Hey-Jarvis_en_wasm_v2_1_0/Hey-Jarvis_en_wasm_v2_1_0.ppn on my Ubuntu machine`)

```
npx pvbase64 \
-i ${DOWNLOADED_PPN_PATH} \
-o src/hey_jarvis.js \
-n heyJarvisKeywordModel
```
**Wire it up**
1. Copy your `AccessKey` from the [Picovoice Console](https://console.picovoice.ai/) 
2. Create a file within `src` called `VoiceWidget.js` and paste the below into it. The code uses Porcupine's hook to create and start the wake word detection. Peplace `${ACCESS_KEY}` with yours.
```
import {useEffect, useState} from "react";
import {usePorcupine} from "@picovoice/porcupine-react";
import heyJarvisKeywordModel from "./hey_jarvis"
import modelParams from "./porcupine_params";
export default function VoiceWidget() {
  const [keywordDetections, setKeywordDetections] = useState([]);
  const {
    keywordDetection,
    isLoaded,
    isListening,
    error,
    init,
    start,
    stop,
    release
  } = usePorcupine();
  const initEngine = async () => {
    await init(
      ${ACCESS_KEY},
      {
        "base64": heyJarvisKeywordModel,
        "label": "Hey Jarvis"
      },
      {base64: modelParams}
    );
    start()
  }
  useEffect(() => {
    if (keywordDetection !== null) {
      setKeywordDetections((oldVal) =>
        [...oldVal, keywordDetection.label])
    }
  }, [keywordDetection])
  return (
    <div className="voice-widget">
      <h3>
        <label>
          <button
            className="init-button"
            onClick={() => initEngine()}
          >
            Start
          </button>
        </label>
      </h3>
      {keywordDetections.length > 0 && (
        <ul>
          {keywordDetections.map((label, index) => (
            <li key={index}>{label}</li>
          ))}
        </ul>
      )}
    </div>
  );
}
```
3. Modify the `App.js` to display the `VoiceWidget` and click start:
```
import './App.css';
import VoiceWidget from "./VoiceWidget";
function App() {
  return (
    <div className="App">
      <h1>
        Porcupine React Demo
      </h1>
      <VoiceWidget />
    </div>
  );
}
export default App;
```
Looking for more?
Explore other languages on the Picovoice Console and check out for fully-working demos with Porcupine on [GitHub](https://github.com/Picovoice/porcupine/tree/master/demo/react).