ブラウザでおしゃべりさせようと思ったら
ブラウザも進化して、音声で入出力できる機能ができましたね。すごい時代です。初老の自分には隔世の感があります
いわゆる音声認識と音声合成と呼ばれる機能ですが、Angular2の環境でやってみようと思ったら、Javascriptで解説されているページのサンプルコードを貼っても動作しませんでした…
そこで、今回はこちらのページを参考に、Angular2の環境で音声認識と音声合成を試してみようと思います。
準備
lodashというものをインストール、importする必要があります。
方法に関してはこちらとこちらを参考にしました。
インストールは、下記のコマンドを実行してください。
npm install --save lodash
npm install --save-dev @types/lodash
importは、音声認識のサービス内に記載しました。
import * as _ from 'lodash';
こちらのサービスモジュールは、次の節で出てきます。
Angular側のプログラム
プログラムは3つ用意しました。
- マイクとスピーカーを使うcomponent
- 音声認識service
- 音声合成service
1のcomponentから2,3のserviceを呼出す形です。
音声認識service
参考にさせていただいたサイト通りで完璧でした。
英語でしたので、分かりにくい場合に参照いただけるように、こちらに再掲します。
(please refer to the original site)
私は日本語で使ったので、langだけja-JPに変更しました。
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
なんと、先ほどのサイトは、音声認識だけで音声合成の記述がありませんでした。どこかからサンプルプログラムを参照させて頂いたのですが、今は見つかりませんでしたので、手元のプログラムを貼り付けておきます。
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
テキストのチャットボットなどの呼出を行なう想定です。
画面には、ブラウザからマイクを使うボタンを置いてください。
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);
});
}
}
これで、画面でマイクボタンを押して、話かけて、(マイクを止めて)チャットボットから返事が来て、それをブラウザで読み上げるアプリケーションができました。
今回は以上です。お疲れ様でした
そのうち、WebAudioAPIなど、ブラウザでできることを試してみたいと思います。
(終わり)