Skip to content

Commit c15d05a

Browse files
committed
Web speech API update
1 parent 64f9c5b commit c15d05a

File tree

5 files changed

+128
-24
lines changed

5 files changed

+128
-24
lines changed

src/app/components/ai/ai.component.html

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,19 @@ <h1 class="mat-display-1">Angular 5 AI</h1>
99
</div>
1010
</mat-card-content>
1111

12-
<mat-input-container>
13-
<input matInput [(ngModel)]="formInput" min="2" placeholder="Your Message..." (keyup.enter)="sendMessageToBot()" type="text">
14-
</mat-input-container>
12+
<div class="message-container">
13+
<mat-card-actions class="voice-button">
14+
<button mat-icon-button (click)="startTalkingToBot()">
15+
<mat-icon>keyboard_voice</mat-icon>
16+
</button>
17+
</mat-card-actions>
18+
<mat-input-container>
19+
<input matInput [(ngModel)]="formInput" min="2" placeholder="Your Message..." (keyup.enter)="sendMessageToBot()" type="text">
20+
</mat-input-container>
21+
</div>
1522

1623
<mat-card-actions class="button center">
1724
<button mat-raised-button (click)="sendMessageToBot()">Send</button>
1825
</mat-card-actions>
19-
26+
2027
</mat-card>

src/app/components/ai/ai.component.scss

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,12 @@
1111
word-wrap: break-word;
1212
}
1313

14+
.message-container {
15+
display: flex;
16+
flex-direction: row;
17+
justify-content: center;
18+
}
19+
1420
.message.to {
1521
background-color: $darkblue;
1622
color: $white;
@@ -32,7 +38,19 @@
3238
display: inline;
3339
}
3440

41+
.mat-form-field {
42+
width: 100%;
43+
}
44+
3545
.mat-raised-button {
3646
background-color: $darkblue;
3747
color: $white;
48+
}
49+
50+
.voice-button {
51+
border-radius: 50%;
52+
width: 40px;
53+
height: 40px;
54+
line-height: 24px;
55+
padding: 8px 20px 8px 8px;
3856
}
Lines changed: 42 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Component, OnInit } from '@angular/core';
1+
import { Component, OnInit, OnDestroy } from '@angular/core';
22

33
import { Observable } from 'rxjs/Observable';
44
import 'rxjs/add/operator/scan';
@@ -11,21 +11,46 @@ import { Message } from '../../model/message';
1111
templateUrl: './ai.component.html',
1212
styleUrls: ['./ai.component.scss']
1313
})
14-
export class AiComponent implements OnInit {
15-
allMessages: Observable<Message[]>;
16-
formInput: string;
17-
18-
constructor(public ai: AiService) {
19-
}
20-
21-
ngOnInit() {
22-
this.allMessages = this.ai.conversation.asObservable()
23-
.scan((acc, val) => acc.concat(val) );
24-
}
25-
26-
sendMessageToBot() {
27-
this.ai.converse(this.formInput);
28-
this.formInput = '';
29-
}
14+
export class AiComponent implements OnInit, OnDestroy {
15+
allMessages: Observable<Message[]>;
16+
formInput: string;
17+
18+
constructor(public ai: AiService) {
19+
this.formInput = '';
20+
}
21+
22+
ngOnInit() {
23+
this.allMessages = this.ai.conversation.asObservable()
24+
.scan((acc, val) => acc.concat(val) );
25+
}
26+
27+
ngOnDestroy() {
28+
this.ai.destroyVoiceConversation();
29+
}
30+
31+
sendMessageToBot() {
32+
this.ai.textConversation(this.formInput);
33+
this.formInput = '';
34+
}
35+
36+
startTalkingToBot() {
37+
this.ai.voiceConversation()
38+
.subscribe(
39+
(value) => {
40+
this.formInput = value;
41+
console.log(value);
42+
},
43+
(err) => {
44+
console.log(err);
45+
if (err.error) {
46+
// console.log("Talking error");
47+
this.startTalkingToBot();
48+
}
49+
},
50+
() => {
51+
// console.log("Talking complete");
52+
this.startTalkingToBot();
53+
});
54+
}
3055
}
3156

src/app/interface/Iwindow.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export interface IWindow extends Window {
2+
webkitSpeechRecognition: any;
3+
SpeechRecognition: any;
4+
}

src/app/service/ai.service.ts

Lines changed: 53 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,26 @@
1-
import { Injectable } from '@angular/core';
1+
import { Injectable, NgZone } from '@angular/core';
22
import { environment } from '../../environments/environment';
3+
import * as lodash from "lodash";
34

45
import { Observable } from 'rxjs/Observable';
56
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
67

78
import { ApiAiClient } from 'api-ai-javascript';
89
import { Message } from '../model/message'
10+
import { IWindow } from '../interface/iwindow'
911

1012
@Injectable()
1113
export class AiService {
1214
readonly token = environment.dialogflow.angularAIBot;
1315
readonly client = new ApiAiClient({ accessToken: this.token });
1416

17+
speechRecognition: any;
1518
conversation = new BehaviorSubject<Message[]>([]);
1619

17-
constructor() {
20+
constructor(private zone: NgZone) {
1821
}
1922

20-
converse(msg: string) {
23+
textConversation(msg: string) {
2124
const userMessage = new Message(msg, 'user');
2225
this.update(userMessage);
2326
return this.client.textRequest(msg)
@@ -31,4 +34,51 @@ export class AiService {
3134
update(msg: Message) {
3235
this.conversation.next([msg]);
3336
}
37+
38+
voiceConversation(): Observable<string> {
39+
return Observable.create(observer => {
40+
const { webkitSpeechRecognition }: IWindow = <IWindow>window;
41+
this.speechRecognition = new webkitSpeechRecognition();
42+
this.speechRecognition.continuous = false;
43+
this.speechRecognition.interimResults = false;
44+
this.speechRecognition.lang = 'en-us';
45+
this.speechRecognition.maxAlternatives = 0;
46+
47+
this.speechRecognition.onresult = speech => {
48+
let sentence: string = "";
49+
if (speech.results) {
50+
var result = speech.results[speech.resultIndex];
51+
var transcript = result[0].transcript;
52+
if (result.isFinal) {
53+
if (result[0].confidence < 0.1) {
54+
console.log("Unrecognized result - Please try again");
55+
}
56+
else {
57+
sentence = lodash.trim(transcript);
58+
console.log("Did you said? -> " + sentence + " , If not then say something else...");
59+
}
60+
}
61+
}
62+
this.zone.run(() => {
63+
observer.next(sentence);
64+
});
65+
};
66+
67+
this.speechRecognition.onerror = error => {
68+
observer.error(error);
69+
};
70+
71+
this.speechRecognition.onend = () => {
72+
observer.complete();
73+
};
74+
75+
this.speechRecognition.start();
76+
// console.log("I'm listening...");
77+
});
78+
}
79+
80+
destroyVoiceConversation() {
81+
if (this.speechRecognition)
82+
this.speechRecognition.stop();
83+
}
3484
}

0 commit comments

Comments
 (0)