Using browser Speech Synthesis capabilities (on an Angular App)
Tags: angular, webdev, javascript, browser
Published: 2023-06-10 22:05:49

Guess what? 
I've been traveling around Germany! But here's the kicker: instead of diligently learning Deutsch like a responsible adult, I've decided to take a shortcut and create my own app to handle everything for me. Genius or madness? We'll see!

So, the first obstacle I encountered was the pronunciation of those tongue-twisting German words. Seriously, they sound like a bunch of cats having a karaoke session. But fear not, for my app comes to the rescue! Not only does it provide translations, but it also teaches me how to pronounce those words correctly. I'll be mastering German like a pro in no time, or at least pretending to while giggling at my own attempts..

![Preview of the real app](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zyck2qc0lk19edl3x8ev.png)

For that, and to have it working offline, I went for the browser capabilities and [Web Speech API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Speech_API) 

I decided to go all-in and use Angular for this app. Why? Well, let's just say I have a soft spot for Angular's sleekness and charm. But hey, don't fret if you're not an Angular enthusiast like me! The beauty of this project is that it's written in good ol' JavaScript, so you can take this linguistic journey with any framework you fancy. It's a choose-your-own-adventure kind of deal!

First step: just created a service to handle this:

```
export class SpeechService {
  synthesis = window.speechSynthesis;

  start(text: string, rate = 1) {
    const textToSpeech = new SpeechSynthesisUtterance(text);
    textToSpeech.lang = "de-DE";
    textToSpeech.text = text;
    textToSpeech.rate = rate;

    const voice = speechSynthesis.getVoices().filter((voice) => {
      return voice.name === "Google Deutsch";
    })[0];
    textToSpeech.voice = voice;

    this.synthesis.speak(textToSpeech);
  }
}
```

The bad part of that from my experience, this only work properly (with a correct accent) in Chrome ...
To see what voices are available, you can check [here](https://developer.mozilla.org/en-US/docs/Web/API/SpeechSynthesis/getVoices)

And it's used for this part (I only care about Deutsch):
```
    const voice = speechSynthesis.getVoices().filter((voice) => {
      return voice.name === "Google Deutsch";
    })[0];
```

To use this, I have a simple component that calls this service

```
@Component({
  selector: 'app-speech',
  standalone: true,
  template: `
  <form class="speech-form" [formGroup]="formGroup">
    <label style="margin-bottom: 10px">Please Insert German Word</label>
    <input formControlName="text" style="margin-bottom: 20px" />
    <button
      style="margin-bottom: 20px"
      (click)="handleButtonStartClick($event, 1)"
    >
      Say It
    </button>
    <button (click)="handleButtonStartClick($event, 0.4)">Say It Slowly</button>
  </form>
  `,
  styleUrls: ['./speech.component.css'],
  imports: [ReactiveFormsModule],
})
export class SpeechComponent {
  formGroup = new FormGroup({
    text: new FormControl('', [Validators.required]),
  });

  constructor(private speechService: SpeechService) {}

  handleButtonStartClick(e: Event, speed: number) {
    e.preventDefault();
    if (!!this.formGroup.controls?.text?.value) {
      this.speechService.start(this.formGroup.controls.text.value, speed);
    }
  }
}
```

There is a button to allows it to speak, and other that is set to say it slowly (0.4 speed), and believe me, to understand **Deutsch **words, I need it.

If you want to test it, just for it [here on stackblitz](https://stackblitz.com/edit/stackblitz-starters-rpxojd?file=src%2Fmain.ts)

In the real app, it also have SpeechRecognition capabilities, maybe in the future I can share it as well.

Tell me what you thing, and if you find it interesting fell free to fork it and try it yourself.