DEV Community

Dilek Karasoy for Picovoice

Posted on

Speech Recognition with Angular

On day 28, we'll work on adding keyword spotting with Porcupine Angular SDK. Keyword spotting is the first defined problem in speech recognition. It enables applications such as wake word detection.

1. Create a new Angular project:

ng new porcupine-angular
Enter fullscreen mode Exit fullscreen mode

2. Install the dependencies:

npm install \
@picovoice/porcupine-angular @picovoice/web-voice-processor
Enter fullscreen mode Exit fullscreen mode
  1. Download the Porcupine model and turn the binary model into a base64 string.
npx pvbase64 \
-i ${DOWNLOADED_MODEL_PATH} \
-o src/lib/porcupine_params.js
Enter fullscreen mode Exit fullscreen mode

Do not forget to replace ${DOWNLOADED_MODEL_PATH} (it's a unique path and depends on where you save the model such as ~/Downloads/porcupine_params.pv).

  1. Run the local server to load the page:
ng serve
Enter fullscreen mode Exit fullscreen mode
  1. Train Wake Word Models
    Sign up for Picovoice Console for free and go to the Porcupine Page. Type in Hey Jarvis (or another phrase that you want to build the model for.), select Web (WASM) as the platform and click on Download. Once you unzip the downloaded file, you see a file with the suffix .ppn. That's the model.

  2. Transform the .ppn model into a base64 string.

npx pvbase64 \
-i ${DOWNLOADED_PPN_PATH} \
-o src/lib/hey_jarvis.js \
-n heyJarvisKeywordModel
Enter fullscreen mode Exit fullscreen mode

Again, do not forget to replace ${DOWNLOADED_PPN_PATH} (e.g. ~/Downloads/Hey-Jarvis_en_wasm_v2_1_0/Hey-Jarvis_en_wasm_v2_1_0.ppn)

  1. Go to Picovoice Console's dashboard. Copy your AccessKey.
  2. Create voice_widget.component.ts and paste the below.
import { Component, OnDestroy } from '@angular/core';
import { Subscription } from 'rxjs';

import { PorcupineService } from '@picovoice/porcupine-angular';

// @ts-ignore
import { modelParams } from '../lib/porcupine_params';
// @ts-ignore
import heyJarvisKeywordModel from '../lib/hey_jarvis';

@Component({
  selector: 'app-voice-widget',
  templateUrl: './voice_widget.component.html',
  styleUrls: ['./voice_widget.component.scss']
})
export class VoiceWidgetComponent implements OnDestroy {
  private keywordSubscription: Subscription;

  detections: Array<string> = [];

  constructor(private porcupineService: PorcupineService) {
    this.keywordSubscription = 
        porcupineService.keywordDetection$.subscribe(
      porcupineSubscription => {
        this.detections = 
            [...this.detections, porcupineSubscription.label];
      });
  }

  ngOnDestroy(): void {
    this.keywordSubscription.unsubscribe();
    this.porcupineService.release();
  }

  public async initEngine(): Promise<void> {
    await this.porcupineService.release();
    try {
      await this.porcupineService.init(
        ${ACCESS_KEY},
        {base64: heyJarvisKeywordModel, label: "Hey Jarvis"},
        { base64: modelParams }
      );
      await this.porcupineService.start();
    }
    catch (error: any) {

    }
  }
}
Create voice_widget.component.html and paste the following into it.
<div class="voice-widget">
    <h1>VoiceWidget</h1>
    <h3>
      <button class="start-button" (click)="initEngine()">
        Start
      </button>
    </h3>

    <ul>
      <li *ngFor="let keywordLabel of detections">
        "{{ keywordLabel }}"
      </li>
    </ul>
</div>
Enter fullscreen mode Exit fullscreen mode

Update app.component.ts

import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent {
  title = 'porcupine-angular-demo-porcupine';
  show = true;

  toggle(): void {
    this.show = !this.show;
  }
}
Enter fullscreen mode Exit fullscreen mode

Update app.module.ts

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

import { AppComponent } from './app.component';
import { VoiceWidgetComponent } from "./voice_widget.component"

@NgModule({
  declarations: [
    AppComponent,
    VoiceWidgetComponent
  ],
  imports: [
    BrowserModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }
Enter fullscreen mode Exit fullscreen mode

If it doesn't work, make sure that you replaced the ${ACCESS_KEY} with your AccessKey obtained from Picovoice Console. You can also check the original article or open-source repo and create an issue under the repo to get technical support.

Top comments (0)