@wenlongche/nativescript-speech-recognition 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ export * from "./speech-recognition.ios";
2
+
3
+ export * from "./speech-recognition.common";
package/package.json ADDED
@@ -0,0 +1,76 @@
1
+ {
2
+ "name": "@wenlongche/nativescript-speech-recognition",
3
+ "version": "2.0.0",
4
+ "description": "Fork of nativescript-speech-recognition - Speech to text plugin, leveraging iOS and Android's built-in recognition engines.",
5
+ "main": "speech-recognition",
6
+ "typings": "index.d.ts",
7
+ "nativescript": {
8
+ "platforms": {
9
+ "android": "3.0.0",
10
+ "ios": "3.0.0"
11
+ }
12
+ },
13
+ "scripts": {
14
+ "tsc": "tsc -skipLibCheck",
15
+ "build": "npm i && npm run tsc",
16
+ "postclone": "npm i && cd ../demo && npm i && cd ../src && npm run plugin.link",
17
+ "test.android": "npm i && npm run tsc && npm run tslint && cd ../demo && tns build android && tns test android --justlaunch",
18
+ "test.ios": "npm i && npm run tsc && npm run tslint && cd ../demo && tns build ios && tns test ios --justlaunch",
19
+ "tslint": "cd .. && tslint \"**/*.ts\" --config tslint.json --exclude \"**/node_modules/**\"",
20
+ "plugin.link": "npm link && cd ../demo && npm link @wenlongche/nativescript-speech-recognition && cd ../src",
21
+ "plugin.tscwatch": "npm run tsc -- -w",
22
+ "demo.ios": "npm run build && cd ../demo && tns run ios",
23
+ "demo.android": "npm run build && cd ../demo && tns run android",
24
+ "demo.android.clean": "npm run build && cd ../demo && tns plugin remove nativescript-speech-recognition && tns plugin add ../src && tns run android",
25
+ "demo.reset": "cd ../demo && rimraf platforms",
26
+ "plugin.prepare": "npm run tsc && cd ../demo && tns plugin remove nativescript-speech-recognition && tns plugin add ../src",
27
+ "clean": "cd ../demo && rimraf hooks node_modules platforms && cd ../src && rimraf node_modules && npm run plugin.link",
28
+ "ci.tslint": "npm i && tslint '**/*.ts' --config '../tslint.json' --exclude '**/node_modules/**'",
29
+ "changelog": "conventional-changelog -i ../CHANGELOG.md -s -r 0",
30
+ "changelog:add": "git add ../CHANGELOG.md && git commit -m 'updated CHANGELOG.md'"
31
+ },
32
+ "repository": {
33
+ "type": "git",
34
+ "url": "https://github.com/wenlongche/nativescript-speech-recognition.git"
35
+ },
36
+ "keywords": [
37
+ "NativeScript",
38
+ "JavaScript",
39
+ "iOS",
40
+ "Siri",
41
+ "Speech to text",
42
+ "Speech",
43
+ "Recognition",
44
+ "Voice"
45
+ ],
46
+ "author": {
47
+ "name": "Wenlong Che",
48
+ "email": "wenlong.che@gmail.com"
49
+ },
50
+ "contributors": [
51
+ {
52
+ "name": "Eddy Verbruggen",
53
+ "email": "eddyverbruggen@gmail.com",
54
+ "url": "https://github.com/EddyVerbruggen"
55
+ },
56
+ {
57
+ "name": "Brad Martin",
58
+ "email": "bradwaynemartin@gmail.com",
59
+ "url": "https://github.com/bradmartin"
60
+ }
61
+ ],
62
+ "bugs": {
63
+ "url": "https://github.com/wenlongche/nativescript-speech-recognition/issues"
64
+ },
65
+ "license": "MIT",
66
+ "homepage": "https://github.com/wenlongche/nativescript-speech-recognition",
67
+ "readmeFilename": "README.md",
68
+ "devDependencies": {
69
+ "@nativescript/core": "~7.0.5",
70
+ "@nativescript/types": "~7.0.4",
71
+ "conventional-changelog-cli": "^1.3.2",
72
+ "rimraf": "^3.0.2",
73
+ "tslint": "~6.1.3",
74
+ "typescript": "~3.9.7"
75
+ }
76
+ }
@@ -0,0 +1,10 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <plist version="1.0">
4
+ <dict>
5
+ <key>NSSpeechRecognitionUsageDescription</key>
6
+ <string> </string>
7
+ <key>NSMicrophoneUsageDescription</key>
8
+ <string> </string>
9
+ </dict>
10
+ </plist>
@@ -0,0 +1,15 @@
1
+ import { SpeechRecognitionApi, SpeechRecognitionOptions } from "./speech-recognition.common";
2
+ export declare class SpeechRecognition implements SpeechRecognitionApi {
3
+ private onPermissionGranted;
4
+ private onPermissionRejected;
5
+ private recognizer;
6
+ private listeningIntent;
7
+ private accumulatedText;
8
+ constructor();
9
+ available(): Promise<boolean>;
10
+ requestPermission(): Promise<boolean>;
11
+ startListening(options: SpeechRecognitionOptions): Promise<boolean>;
12
+ stopListening(): Promise<any>;
13
+ private wasPermissionGranted;
14
+ private _requestPermission;
15
+ }
@@ -0,0 +1,195 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SpeechRecognition = void 0;
4
+ var core_1 = require("@nativescript/core");
5
+ var AppPackageName = useAndroidX() ? global.androidx.core.app : android.support.v4.app;
6
+ var ContentPackageName = useAndroidX() ? global.androidx.core.content : android.support.v4.content;
7
+ function useAndroidX() {
8
+ return global.androidx && global.androidx.appcompat;
9
+ }
10
+ var SpeechRecognition = (function () {
11
+ function SpeechRecognition() {
12
+ var _this = this;
13
+ this.recognizer = null;
14
+ this.listeningIntent = null;
15
+ this.accumulatedText = "";
16
+ var self = this;
17
+ core_1.Application.android.on(core_1.AndroidApplication.activityRequestPermissionsEvent, function (args) {
18
+ for (var i = 0; i < args.permissions.length; i++) {
19
+ if (args.grantResults[i] === android.content.pm.PackageManager.PERMISSION_DENIED) {
20
+ if (self.onPermissionRejected) {
21
+ self.onPermissionRejected("Please allow access to the Microphone and try again.");
22
+ }
23
+ else {
24
+ console.log("Please allow access to the Microphone and try again. (tip: pass in a reject to receive this message in your app)");
25
+ }
26
+ return;
27
+ }
28
+ }
29
+ if (self.onPermissionGranted) {
30
+ self.onPermissionGranted();
31
+ }
32
+ });
33
+ core_1.Application.on(core_1.Application.suspendEvent, function (args) {
34
+ if (_this.recognizer !== null) {
35
+ _this.stopListening();
36
+ }
37
+ });
38
+ }
39
+ SpeechRecognition.prototype.available = function () {
40
+ return new Promise(function (resolve, reject) {
41
+ resolve(android.speech.SpeechRecognizer.isRecognitionAvailable(core_1.Utils.android.getApplicationContext()));
42
+ });
43
+ };
44
+ SpeechRecognition.prototype.requestPermission = function () {
45
+ var _this = this;
46
+ console.log(">> requestPermission");
47
+ return new Promise(function (resolve, reject) {
48
+ _this._requestPermission(function () { return resolve(true); }, function () { return resolve(false); });
49
+ });
50
+ };
51
+ SpeechRecognition.prototype.startListening = function (options) {
52
+ var _this = this;
53
+ console.log(">> startListening");
54
+ return new Promise(function (resolve, reject) {
55
+ var onPermissionGranted = function () {
56
+ var self = _this;
57
+ function sendBackResults(results, partial) {
58
+ var transcripts = results.getStringArrayList(android.speech.SpeechRecognizer.RESULTS_RECOGNITION);
59
+ var transcript = null;
60
+ if (!transcripts.isEmpty()) {
61
+ transcript = transcripts.get(0);
62
+ }
63
+ if (options.listenContinuously) {
64
+ if (!partial && transcript) {
65
+ if (self.accumulatedText.length > 0) {
66
+ self.accumulatedText += " " + transcript;
67
+ }
68
+ else {
69
+ self.accumulatedText = transcript;
70
+ }
71
+ transcript = self.accumulatedText;
72
+ }
73
+ else if (partial && transcript) {
74
+ transcript = self.accumulatedText.length > 0
75
+ ? self.accumulatedText + " " + transcript
76
+ : transcript;
77
+ }
78
+ }
79
+ if (transcript) {
80
+ options.onResult({
81
+ text: transcript,
82
+ finished: !partial
83
+ });
84
+ }
85
+ }
86
+ var loopHandler = new android.os.Handler(android.os.Looper.getMainLooper());
87
+ loopHandler.post(new java.lang.Runnable({
88
+ run: function () {
89
+ _this.recognizer = android.speech.SpeechRecognizer.createSpeechRecognizer(core_1.Utils.android.getApplicationContext());
90
+ _this.recognizer.setRecognitionListener(new android.speech.RecognitionListener({
91
+ onReadyForSpeech: function (params) {
92
+ resolve(true);
93
+ },
94
+ onBeginningOfSpeech: function () {
95
+ },
96
+ onRmsChanged: function (rmsdB) {
97
+ },
98
+ onBufferReceived: function (buffer) {
99
+ },
100
+ onEndOfSpeech: function () {
101
+ },
102
+ onError: function (error) {
103
+ console.log("Error: " + error);
104
+ if (options.listenContinuously && self.recognizer && self.listeningIntent &&
105
+ (error === android.speech.SpeechRecognizer.ERROR_SPEECH_TIMEOUT ||
106
+ error === android.speech.SpeechRecognizer.ERROR_NO_MATCH)) {
107
+ self.recognizer.cancel();
108
+ self.recognizer.startListening(self.listeningIntent);
109
+ }
110
+ else {
111
+ options.onError && options.onError(error);
112
+ reject(error);
113
+ }
114
+ },
115
+ onResults: function (results) {
116
+ sendBackResults(results, false);
117
+ if (options.listenContinuously && self.recognizer && self.listeningIntent) {
118
+ self.recognizer.startListening(self.listeningIntent);
119
+ }
120
+ },
121
+ onPartialResults: function (partialResults) {
122
+ if (options.returnPartialResults) {
123
+ sendBackResults(partialResults, true);
124
+ }
125
+ },
126
+ onEvent: function (eventType, params) {
127
+ }
128
+ }));
129
+ }
130
+ }));
131
+ var intent = new android.content.Intent(android.speech.RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
132
+ intent.putExtra(android.speech.RecognizerIntent.EXTRA_LANGUAGE_MODEL, android.speech.RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
133
+ intent.putExtra(android.speech.RecognizerIntent.EXTRA_CALLING_PACKAGE, "voice.recognition.test");
134
+ if (options.locale) {
135
+ intent.putExtra(android.speech.RecognizerIntent.EXTRA_LANGUAGE, options.locale);
136
+ }
137
+ if (options.returnPartialResults) {
138
+ intent.putExtra(android.speech.RecognizerIntent.EXTRA_PARTIAL_RESULTS, true);
139
+ }
140
+ intent.putExtra(android.speech.RecognizerIntent.EXTRA_MAX_RESULTS, 100);
141
+ if (options.listenContinuously) {
142
+ _this.listeningIntent = intent;
143
+ _this.accumulatedText = "";
144
+ }
145
+ loopHandler.post(new java.lang.Runnable({
146
+ run: function () {
147
+ _this.recognizer.startListening(intent);
148
+ }
149
+ }));
150
+ };
151
+ if (!_this.wasPermissionGranted()) {
152
+ _this._requestPermission(onPermissionGranted, reject);
153
+ return;
154
+ }
155
+ onPermissionGranted();
156
+ });
157
+ };
158
+ SpeechRecognition.prototype.stopListening = function () {
159
+ var _this = this;
160
+ return new Promise(function (resolve, reject) {
161
+ if (_this.recognizer === null) {
162
+ reject("Not running");
163
+ return;
164
+ }
165
+ var loopHandler = new android.os.Handler(android.os.Looper.getMainLooper());
166
+ loopHandler.post(new java.lang.Runnable({
167
+ run: function () {
168
+ _this.recognizer.stopListening();
169
+ _this.recognizer.cancel();
170
+ _this.recognizer.destroy();
171
+ _this.recognizer = null;
172
+ _this.listeningIntent = null;
173
+ _this.accumulatedText = "";
174
+ resolve();
175
+ }
176
+ }));
177
+ });
178
+ };
179
+ SpeechRecognition.prototype.wasPermissionGranted = function () {
180
+ var hasPermission = android.os.Build.VERSION.SDK_INT < 23;
181
+ if (!hasPermission) {
182
+ hasPermission = android.content.pm.PackageManager.PERMISSION_GRANTED ===
183
+ ContentPackageName.ContextCompat.checkSelfPermission(core_1.Utils.android.getApplicationContext(), android.Manifest.permission.RECORD_AUDIO);
184
+ }
185
+ return hasPermission;
186
+ };
187
+ SpeechRecognition.prototype._requestPermission = function (onPermissionGranted, reject) {
188
+ this.onPermissionGranted = onPermissionGranted;
189
+ this.onPermissionRejected = reject;
190
+ AppPackageName.ActivityCompat.requestPermissions(core_1.Application.android.foregroundActivity || core_1.Application.android.startActivity, [android.Manifest.permission.RECORD_AUDIO], 444);
191
+ };
192
+ return SpeechRecognition;
193
+ }());
194
+ exports.SpeechRecognition = SpeechRecognition;
195
+ //# sourceMappingURL=speech-recognition.android.js.map
@@ -0,0 +1,17 @@
1
+ export interface SpeechRecognitionTranscription {
2
+ text: string;
3
+ finished: boolean;
4
+ }
5
+ export interface SpeechRecognitionOptions {
6
+ locale?: string;
7
+ returnPartialResults?: boolean;
8
+ listenContinuously?: boolean;
9
+ onResult: (transcription: SpeechRecognitionTranscription) => void;
10
+ onError?: (error: string | number) => void;
11
+ }
12
+ export interface SpeechRecognitionApi {
13
+ available(): Promise<boolean>;
14
+ requestPermission(): Promise<boolean>;
15
+ startListening(options: SpeechRecognitionOptions): Promise<boolean>;
16
+ stopListening(): Promise<any>;
17
+ }
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=speech-recognition.common.js.map
@@ -0,0 +1,14 @@
1
+ import { SpeechRecognitionApi, SpeechRecognitionOptions } from "./speech-recognition.common";
2
+ export declare class SpeechRecognition implements SpeechRecognitionApi {
3
+ private recognitionRequest;
4
+ private audioEngine;
5
+ private speechRecognizer;
6
+ private recognitionTask;
7
+ private inputNode;
8
+ private audioSession;
9
+ constructor();
10
+ available(): Promise<boolean>;
11
+ requestPermission(): Promise<boolean>;
12
+ startListening(options: SpeechRecognitionOptions): Promise<boolean>;
13
+ stopListening(): Promise<any>;
14
+ }
@@ -0,0 +1,114 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SpeechRecognition = void 0;
4
+ var core_1 = require("@nativescript/core");
5
+ var SpeechRecognition = (function () {
6
+ function SpeechRecognition() {
7
+ this.recognitionRequest = null;
8
+ this.audioEngine = null;
9
+ this.speechRecognizer = null;
10
+ this.recognitionTask = null;
11
+ this.inputNode = null;
12
+ this.audioSession = null;
13
+ this.audioEngine = AVAudioEngine.new();
14
+ }
15
+ SpeechRecognition.prototype.available = function () {
16
+ return new Promise(function (resolve, reject) {
17
+ resolve(parseInt(core_1.Device.osVersion) >= 10);
18
+ });
19
+ };
20
+ SpeechRecognition.prototype.requestPermission = function () {
21
+ return new Promise(function (resolve, reject) {
22
+ SFSpeechRecognizer.requestAuthorization(function (status) {
23
+ if (status !== 3) {
24
+ resolve(false);
25
+ return;
26
+ }
27
+ AVAudioSession.sharedInstance().requestRecordPermission(function (granted) {
28
+ resolve(granted);
29
+ });
30
+ });
31
+ });
32
+ };
33
+ SpeechRecognition.prototype.startListening = function (options) {
34
+ var _this = this;
35
+ return new Promise(function (resolve, reject) {
36
+ var locale = NSLocale.alloc().initWithLocaleIdentifier(options.locale ? options.locale : core_1.Device.language);
37
+ _this.speechRecognizer = SFSpeechRecognizer.alloc().initWithLocale(locale);
38
+ if (_this.recognitionTask !== null) {
39
+ _this.recognitionTask.cancel();
40
+ _this.recognitionTask = null;
41
+ }
42
+ SFSpeechRecognizer.requestAuthorization(function (status) {
43
+ if (status !== 3) {
44
+ options.onError && options.onError("Not authorized");
45
+ reject("Not authorized");
46
+ return;
47
+ }
48
+ _this.audioSession = AVAudioSession.sharedInstance();
49
+ _this.audioSession.setCategoryError(AVAudioSessionCategoryRecord);
50
+ _this.audioSession.setModeError(AVAudioSessionModeMeasurement);
51
+ _this.audioSession.setActiveWithOptionsError(true, 1);
52
+ _this.recognitionRequest = SFSpeechAudioBufferRecognitionRequest.new();
53
+ if (!_this.recognitionRequest) {
54
+ options.onError && options.onError("Unable to create an SFSpeechAudioBufferRecognitionRequest object");
55
+ reject("Unable to create an SFSpeechAudioBufferRecognitionRequest object");
56
+ return;
57
+ }
58
+ _this.inputNode = _this.audioEngine.inputNode;
59
+ if (!_this.inputNode) {
60
+ options.onError && options.onError("Audio engine has no input node");
61
+ reject("Audio engine has no input node");
62
+ return;
63
+ }
64
+ _this.recognitionRequest.shouldReportPartialResults = options.returnPartialResults;
65
+ _this.recognitionTask = _this.speechRecognizer.recognitionTaskWithRequestResultHandler(_this.recognitionRequest, function (result, error) {
66
+ if (result !== null) {
67
+ options.onResult({
68
+ finished: result.final,
69
+ text: result.bestTranscription.formattedString
70
+ });
71
+ }
72
+ if (error !== null || (result !== null && result.final)) {
73
+ _this.audioEngine.stop();
74
+ _this.inputNode.removeTapOnBus(0);
75
+ _this.audioSession.setCategoryError(AVAudioSessionCategoryPlayback);
76
+ _this.audioSession.setModeError(AVAudioSessionModeDefault);
77
+ _this.recognitionRequest = null;
78
+ _this.recognitionTask = null;
79
+ }
80
+ if (error !== null) {
81
+ console.log("error in handler: " + error.localizedDescription);
82
+ options.onError && options.onError(error.localizedDescription);
83
+ }
84
+ });
85
+ var that = _this;
86
+ var recordingFormat = _this.inputNode.outputFormatForBus(0);
87
+ _this.inputNode.installTapOnBusBufferSizeFormatBlock(0, 1024, recordingFormat, function (buffer, when) {
88
+ that.recognitionRequest.appendAudioPCMBuffer(buffer);
89
+ });
90
+ _this.audioEngine.prepare();
91
+ resolve(_this.audioEngine.startAndReturnError());
92
+ });
93
+ });
94
+ };
95
+ SpeechRecognition.prototype.stopListening = function () {
96
+ var _this = this;
97
+ return new Promise(function (resolve, reject) {
98
+ if (!_this.audioEngine.running) {
99
+ reject("Not running");
100
+ return;
101
+ }
102
+ _this.audioEngine.stop();
103
+ _this.recognitionRequest.endAudio();
104
+ _this.audioSession.setCategoryError(AVAudioSessionCategoryPlayback);
105
+ _this.audioSession.setModeError(AVAudioSessionModeDefault);
106
+ _this.speechRecognizer = null;
107
+ _this.recognitionTask = null;
108
+ resolve();
109
+ });
110
+ };
111
+ return SpeechRecognition;
112
+ }());
113
+ exports.SpeechRecognition = SpeechRecognition;
114
+ //# sourceMappingURL=speech-recognition.ios.js.map