From c15d05adb3c40c621fc0ffb51f8b591d606d77cb Mon Sep 17 00:00:00 2001 From: Jeroenouw Date: Sun, 5 Nov 2017 12:50:55 +0100 Subject: [PATCH 1/2] Web speech API update --- src/app/components/ai/ai.component.html | 15 +++++-- src/app/components/ai/ai.component.scss | 18 ++++++++ src/app/components/ai/ai.component.ts | 59 ++++++++++++++++++------- src/app/interface/Iwindow.ts | 4 ++ src/app/service/ai.service.ts | 56 +++++++++++++++++++++-- 5 files changed, 128 insertions(+), 24 deletions(-) create mode 100644 src/app/interface/Iwindow.ts diff --git a/src/app/components/ai/ai.component.html b/src/app/components/ai/ai.component.html index b24c7cd..a613e11 100644 --- a/src/app/components/ai/ai.component.html +++ b/src/app/components/ai/ai.component.html @@ -9,12 +9,19 @@

Angular 5 AI

- - - +
+ + + + + + +
- + diff --git a/src/app/components/ai/ai.component.scss b/src/app/components/ai/ai.component.scss index daba5b6..f007aa8 100644 --- a/src/app/components/ai/ai.component.scss +++ b/src/app/components/ai/ai.component.scss @@ -11,6 +11,12 @@ word-wrap: break-word; } +.message-container { + display: flex; + flex-direction: row; + justify-content: center; +} + .message.to { background-color: $darkblue; color: $white; @@ -32,7 +38,19 @@ display: inline; } +.mat-form-field { + width: 100%; +} + .mat-raised-button { background-color: $darkblue; color: $white; +} + +.voice-button { + border-radius: 50%; + width: 40px; + height: 40px; + line-height: 24px; + padding: 8px 20px 8px 8px; } \ No newline at end of file diff --git a/src/app/components/ai/ai.component.ts b/src/app/components/ai/ai.component.ts index de6955b..cdde5f7 100644 --- a/src/app/components/ai/ai.component.ts +++ b/src/app/components/ai/ai.component.ts @@ -1,4 +1,4 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, OnInit, OnDestroy } from '@angular/core'; import { Observable } from 'rxjs/Observable'; import 'rxjs/add/operator/scan'; @@ -11,21 +11,46 @@ import { Message } from '../../model/message'; templateUrl: './ai.component.html', styleUrls: ['./ai.component.scss'] }) -export class AiComponent implements OnInit { - allMessages: Observable; - formInput: string; - - constructor(public ai: AiService) { - } - - ngOnInit() { - this.allMessages = this.ai.conversation.asObservable() - .scan((acc, val) => acc.concat(val) ); - } - - sendMessageToBot() { - this.ai.converse(this.formInput); - this.formInput = ''; - } +export class AiComponent implements OnInit, OnDestroy { + allMessages: Observable; + formInput: string; + + constructor(public ai: AiService) { + this.formInput = ''; + } + + ngOnInit() { + this.allMessages = this.ai.conversation.asObservable() + .scan((acc, val) => acc.concat(val) ); + } + + ngOnDestroy() { + this.ai.destroyVoiceConversation(); + } + + sendMessageToBot() { + this.ai.textConversation(this.formInput); + this.formInput = ''; + } + + startTalkingToBot() { + this.ai.voiceConversation() + .subscribe( + (value) => { + this.formInput = value; + console.log(value); + }, + (err) => { + console.log(err); + if (err.error) { + // console.log("Talking error"); + this.startTalkingToBot(); + } + }, + () => { + // console.log("Talking complete"); + this.startTalkingToBot(); + }); + } } \ No newline at end of file diff --git a/src/app/interface/Iwindow.ts b/src/app/interface/Iwindow.ts new file mode 100644 index 0000000..c6e50d1 --- /dev/null +++ b/src/app/interface/Iwindow.ts @@ -0,0 +1,4 @@ +export interface IWindow extends Window { + webkitSpeechRecognition: any; + SpeechRecognition: any; +} \ No newline at end of file diff --git a/src/app/service/ai.service.ts b/src/app/service/ai.service.ts index 628a5ca..c0b3d79 100644 --- a/src/app/service/ai.service.ts +++ b/src/app/service/ai.service.ts @@ -1,23 +1,26 @@ -import { Injectable } from '@angular/core'; +import { Injectable, NgZone } from '@angular/core'; import { environment } from '../../environments/environment'; +import * as lodash from "lodash"; import { Observable } from 'rxjs/Observable'; import { BehaviorSubject } from 'rxjs/BehaviorSubject'; import { ApiAiClient } from 'api-ai-javascript'; import { Message } from '../model/message' +import { IWindow } from '../interface/iwindow' @Injectable() export class AiService { readonly token = environment.dialogflow.angularAIBot; readonly client = new ApiAiClient({ accessToken: this.token }); + speechRecognition: any; conversation = new BehaviorSubject([]); - constructor() { + constructor(private zone: NgZone) { } - converse(msg: string) { + textConversation(msg: string) { const userMessage = new Message(msg, 'user'); this.update(userMessage); return this.client.textRequest(msg) @@ -31,4 +34,51 @@ export class AiService { update(msg: Message) { this.conversation.next([msg]); } + + voiceConversation(): Observable { + return Observable.create(observer => { + const { webkitSpeechRecognition }: IWindow = window; + this.speechRecognition = new webkitSpeechRecognition(); + this.speechRecognition.continuous = false; + this.speechRecognition.interimResults = false; + this.speechRecognition.lang = 'en-us'; + this.speechRecognition.maxAlternatives = 0; + + this.speechRecognition.onresult = speech => { + let sentence: string = ""; + if (speech.results) { + var result = speech.results[speech.resultIndex]; + var transcript = result[0].transcript; + if (result.isFinal) { + if (result[0].confidence < 0.1) { + console.log("Unrecognized result - Please try again"); + } + else { + sentence = lodash.trim(transcript); + console.log("Did you said? -> " + sentence + " , If not then say something else..."); + } + } + } + this.zone.run(() => { + observer.next(sentence); + }); + }; + + this.speechRecognition.onerror = error => { + observer.error(error); + }; + + this.speechRecognition.onend = () => { + observer.complete(); + }; + + this.speechRecognition.start(); + // console.log("I'm listening..."); + }); + } + + destroyVoiceConversation() { + if (this.speechRecognition) + this.speechRecognition.stop(); + } } From f371db0ece6a8136de86e2ebdaa464f9f3200152 Mon Sep 17 00:00:00 2001 From: Jeroenouw Date: Sun, 5 Nov 2017 13:07:17 +0100 Subject: [PATCH 2/2] Updated DOCS and new release --- README.md | 18 +++++------------- docs/DEVELOPING.md | 35 +++++++++++++++++++++++++++++++++++ docs/SENTENCES.md | 13 +++++++++++++ package-lock.json | 2 +- package.json | 3 ++- src/index.html | 1 - 6 files changed, 56 insertions(+), 16 deletions(-) create mode 100644 docs/DEVELOPING.md create mode 100644 docs/SENTENCES.md diff --git a/README.md b/README.md index e19b25f..7109b20 100644 --- a/README.md +++ b/README.md @@ -17,19 +17,11 @@ A small AI application containing [Angular 5](https://angular.io), [Material](ht * Dialogflow AI * Chatbot -## Example sentences -* Can you get smarter? -* You're boring -* Who is your boss? -* You are funny -* Are we friends? -* I'll be back -* You're wrong -* Nice to see you! -* What's up? -* I don't want to talk -* Today is my birthday -* I need an advice +## Sentences +[A couple of example sentences to get you start talking](https://github.com/jeroenouw/AngularAI/blob/master/docs/SENTENCES.md) + +## Developing +[Quick starting and development](https://github.com/jeroenouw/AngularAI/blob/master/docs/DEVELOPING.md) ## Contributing Want to file a bug, contribute some code, or improve documentation? Feel free to place an [issue](https://github.com/jeroenouw/AngularAI/issues). diff --git a/docs/DEVELOPING.md b/docs/DEVELOPING.md new file mode 100644 index 0000000..d7e54f6 --- /dev/null +++ b/docs/DEVELOPING.md @@ -0,0 +1,35 @@ +## Quick start +First clone this repo: `git clone https://github.com/jeroenouw/AngularAI.git`. +Change directory to this project +Run `npm install` to install all the dependencies. +Run `npm start` to run this project. This will run with the AoT Compiler. +Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files. + +## Development +For own projects please use different token `src/environment/environment.prod.ts` and `src/environment/environment.ts`: +``` dialogflow: { ``` +``` [CHOOSE_A_NAME]': '[YOUR_TOKEN]' ``` +``` }``` + +Run `npm start` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files. + +To build the development environment, run `npm run dist`. + +## Production +To build the default production environment, run `npm run prod`. This will run with the AoT Compiler. +To build the production environment with reduced file size, run `npm run prod:opt` (Takes extra time to build with build optimizer). + +## Speech Options +Available speech recognition options in `src/app/service/ai.service.ts` + +Choose if the API needs to look for further words: +`this.speechRecognition.continuous = false;` + +Show interim results or just final results: +`this.speechRecognition.interimResults = false;` + +Select your speech language: +`this.speechRecognition.lang = 'en-us';` + +Choose the quantity of alternative available matches: +`this.speechRecognition.maxAlternatives = 0;` \ No newline at end of file diff --git a/docs/SENTENCES.md b/docs/SENTENCES.md new file mode 100644 index 0000000..08a96e3 --- /dev/null +++ b/docs/SENTENCES.md @@ -0,0 +1,13 @@ +## Example sentences +* Can you get smarter? +* You're boring +* Who is your boss? +* You are funny +* Are we friends? +* I'll be back +* You're wrong +* Nice to see you! +* What's up? +* I don't want to talk +* Today is my birthday +* I need an advice diff --git a/package-lock.json b/package-lock.json index bb740b4..f990c7c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "ngx-ai", - "version": "1.0.0", + "version": "1.0.1", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index ae4c2ca..2084dd5 100644 --- a/package.json +++ b/package.json @@ -1,11 +1,12 @@ { "name": "ngx-ai", - "version": "1.0.1", + "version": "1.0.2", "author": "Jeroen Ouwehand", "description": "Angular 5 AI", "keywords": [ "angular", "dialogflow", + "web speech api", "google", "material", "chatbot", diff --git a/src/index.html b/src/index.html index aec048b..5a6826b 100644 --- a/src/index.html +++ b/src/index.html @@ -8,7 +8,6 @@ -