LoginSignup
7
9

More than 5 years have passed since last update.

Angular2の環境で、ブラウザの音声認識と音声合成の機能を導入する

Posted at

ブラウザでおしゃべりさせようと思ったら

ブラウザも進化して、音声で入出力できる機能ができましたね。すごい時代です。初老の自分には隔世の感があります:older_man_tone1:

いわゆる音声認識と音声合成と呼ばれる機能ですが、Angular2の環境でやってみようと思ったら、Javascriptで解説されているページのサンプルコードを貼っても動作しませんでした…

そこで、今回はこちらのページを参考に、Angular2の環境で音声認識と音声合成を試してみようと思います。

準備

lodashというものをインストール、importする必要があります。
方法に関してはこちらこちらを参考にしました。

インストールは、下記のコマンドを実行してください。

console
npm install --save lodash
npm install --save-dev @types/lodash

importは、音声認識のサービス内に記載しました。

speech-recognition.service.ts
import * as _ from 'lodash';

こちらのサービスモジュールは、次の節で出てきます。

Angular側のプログラム

プログラムは3つ用意しました。

  1. マイクとスピーカーを使うcomponent
  2. 音声認識service
  3. 音声合成service

1のcomponentから2,3のserviceを呼出す形です。

音声認識service

参考にさせていただいたサイト通りで完璧でした。
英語でしたので、分かりにくい場合に参照いただけるように、こちらに再掲します。
(please refer to the original site
私は日本語で使ったので、langだけja-JPに変更しました。

speech-recognition.service.ts

import { Injectable, NgZone } from '@angular/core';
import { Observable } from 'rxjs/Rx';
import * as _ from "lodash";

interface IWindow extends Window {
    webkitSpeechRecognition: any;
    SpeechRecognition: any;
}

@Injectable()
export class SpeechRecognitionService {
    speechRecognition: any;

    constructor(private zone: NgZone) {
    }

    record(): Observable<string> {

        return Observable.create(observer => {
            const { webkitSpeechRecognition }: IWindow = <IWindow>window;
            this.speechRecognition = new webkitSpeechRecognition();
            //this.speechRecognition = SpeechRecognition;
            this.speechRecognition.continuous = true;
            //this.speechRecognition.interimResults = true;
            this.speechRecognition.lang = 'ja-JP'; // original:en-us
            this.speechRecognition.maxAlternatives = 1;

            this.speechRecognition.onresult = speech => {
                let term: string = "";
                if (speech.results) {
                    var result = speech.results[speech.resultIndex];
                    var transcript = result[0].transcript;
                    if (result.isFinal) {
                        if (result[0].confidence < 0.3) {
                            console.log("Unrecognized result - Please try again");
                        }
                        else {
                            term = _.trim(transcript);
                            console.log("Did you said? -> " + term + " , If not then say something else...");
                        }
                    }
                }
                this.zone.run(() => {
                    observer.next(term);
                });
            };

            this.speechRecognition.onerror = error => {
                observer.error(error);
            };

            this.speechRecognition.onend = () => {
                observer.complete();
            };

            this.speechRecognition.start();
            console.log("Say something - We are listening !!!");
        });
    }

    DestroySpeechObject() {
        if (this.speechRecognition)
            this.speechRecognition.stop();
    }

}

音声合成service

なんと、先ほどのサイトは、音声認識だけで音声合成の記述がありませんでした。どこかからサンプルプログラムを参照させて頂いたのですが、今は見つかりませんでしたので、手元のプログラムを貼り付けておきます。

speech-synthesis.service.ts

import {Injectable, NgZone} from '@angular/core';

interface IWindow extends Window {
  webkitSpeechSynthesis: any;
  SpeechSynthesis: any;
  SpeechSynthesisUtterance: any;
}

@Injectable()
export class SpeechSynthesisService {
  speechSynthesis: any;

  constructor(private zone: NgZone) {
    if ('speechSynthesis' in window) {
      console.log('Your browser supports speech synthesis.');
    } else {
      alert('Sorry! Your browser does not support speech synthesis. Try this on' +
        ' <a href="https://www.google.com/chrome/browser/desktop/index.html">Google Chrome</a>.');
    }
  }

  speak(text: string): void {
    const { SpeechSynthesisUtterance }: IWindow = <IWindow>window;

    let utterance = new SpeechSynthesisUtterance(text);
    utterance.lang = 'ja-JP';
    (<any>window).speechSynthesis.speak(utterance);
  }

}

音声認識と音声合成を利用するcomponent

テキストのチャットボットなどの呼出を行なう想定です。
画面には、ブラウザからマイクを使うボタンを置いてください。

your-component.ts

import { Component, OnInit, Input } from '@angular/core';
import { SpeechRecognitionService } from './speech-recognition.service';
import { SpeechSynthesisService } from './speech-synthesis.service';


@Component({
  selector: 'app-xxx',
  templateUrl: './your.component.html',
  styleUrls: ['./your.component.css']
})
export class YourComponent implements OnInit {

  speechData: string;

  constructor(private speechRecognitionService: SpeechRecognitionService,
              private speechSynthesisService: SpeechSynthesisService
  ) {
    this.speechData = "";
  }

  ngOnInit() {
  }
  ngOnDestroy(){
    this.speechRecognitionService.stop();
  }

  // 音声認識用マイクのON/OFF 
  micOn: boolean = false;
  MicButton(state: boolean): void {
    this.micOn = state;
    if(this.micOn){
      this.activateSpeech();
    } else {
      this.deactivateSpeech();
    }
  }


  activateSpeech(): void {

    this.speechRecognitionService.record()
      .subscribe(
        //listener
        (value) => {
          this.speechData = value;
          console.log(value);
          yourChatBotFunction(value); // ★ここで独自関数を呼出す
        },
        //errror
        (err) => {
          console.log(err);
          if (err.error == "no-speech") {
            console.log("--restatring service--");
            this.activateSpeechSearchMovie();
          }
        },
        //completion
        () => {
          this.showSearchButton = true;
          console.log("--complete--");
          this.activateSpeechSearchMovie();
        });
  }


  deactivateSpeech(): void {
    this.speechRecognitionService.stop();
  }

  // ★独自関数
  // 引数のmessageには、音声認識で認識されたテキストが入る
  // chatbotサーバにテキストを送信し、戻りのテキストを読み上げる
  yourChatBotFunction(message: string): void {
    serverCall(message)
      .then(res => {
        this.speechSynthesisService.speak(res);
      });
  }

}

これで、画面でマイクボタンを押して、話かけて、(マイクを止めて)チャットボットから返事が来て、それをブラウザで読み上げるアプリケーションができました。

今回は以上です。お疲れ様でした:grinning:
そのうち、WebAudioAPIなど、ブラウザでできることを試してみたいと思います。

(終わり)

7
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
9