annyang 2.6.1 → 3.1.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/LICENSE +1 -1
- package/README.md +56 -32
- package/dist/annyang.cjs +361 -0
- package/dist/annyang.cjs.map +1 -0
- package/dist/annyang.d.cts +288 -0
- package/dist/annyang.d.ts +288 -0
- package/dist/annyang.iife.min.js +1 -0
- package/dist/annyang.js +303 -670
- package/dist/annyang.js.map +1 -1
- package/package.json +55 -31
- package/.editorconfig +0 -13
- package/.eslintrc.json +0 -34
- package/.gitattributes +0 -1
- package/.github/ISSUE_TEMPLATE.md +0 -32
- package/.github/PULL_REQUEST_TEMPLATE.md +0 -29
- package/.jshintrc +0 -31
- package/.travis.yml +0 -20
- package/CONTRIBUTING.md +0 -75
- package/Gruntfile.js +0 -144
- package/bower.json +0 -25
- package/demo/css/main.css +0 -152
- package/demo/css/main.min.css +0 -1
- package/demo/images/flickr.png +0 -0
- package/demo/images/footer_background.jpg +0 -0
- package/demo/images/icon_js.png +0 -0
- package/demo/images/icon_speech.png +0 -0
- package/demo/images/icon_user.png +0 -0
- package/demo/images/mini_icon_say.png +0 -0
- package/demo/images/palette.png +0 -0
- package/demo/images/tpscover.jpg +0 -0
- package/demo/index.html +0 -225
- package/demo/vendor/css/default.css +0 -135
- package/demo/vendor/css/github.css +0 -127
- package/demo/vendor/css/tomorrow.css +0 -49
- package/demo/vendor/html/github-btn.html +0 -243
- package/demo/vendor/js/highlight.pack.js +0 -1
- package/dist/annyang.min.js +0 -12
- package/docs/FAQ.md +0 -223
- package/docs/README.md +0 -336
- package/require.js +0 -36
- package/sites/README.md +0 -6
- package/sites/facebook.js +0 -123
- package/sites/facebook.min.js +0 -17
- package/sites/geektime.js +0 -108
- package/sites/geektime.min.js +0 -17
- package/src/annyang.js +0 -680
- package/test/SpecRunner.html +0 -41
- package/test/init_corti.js +0 -1
- package/test/spec/.jshintrc +0 -40
- package/test/spec/BasicSpec.js +0 -1616
- package/test/spec/IssuesSpec.js +0 -41
- package/test/vendor/corti.js +0 -202
- package/yarn.lock +0 -4190
package/dist/annyang.js
CHANGED
|
@@ -1,688 +1,321 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
var
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
var recognition;
|
|
51
|
-
var callbacks = { start: [], error: [], end: [], soundstart: [], result: [], resultMatch: [], resultNoMatch: [], errorNetwork: [], errorPermissionBlocked: [], errorPermissionDenied: [] };
|
|
52
|
-
var autoRestart;
|
|
53
|
-
var lastStartedAt = 0;
|
|
54
|
-
var autoRestartCount = 0;
|
|
55
|
-
var debugState = false;
|
|
56
|
-
var debugStyle = 'font-weight: bold; color: #00f;';
|
|
57
|
-
var pauseListening = false;
|
|
58
|
-
var _isListening = false;
|
|
59
|
-
|
|
60
|
-
// The command matching code is a modified version of Backbone.Router by Jeremy Ashkenas, under the MIT license.
|
|
61
|
-
var optionalParam = /\s*\((.*?)\)\s*/g;
|
|
62
|
-
var optionalRegex = /(\(\?:[^)]+\))\?/g;
|
|
63
|
-
var namedParam = /(\(\?)?:\w+/g;
|
|
64
|
-
var splatParam = /\*\w+/g;
|
|
65
|
-
var escapeRegExp = /[\-{}\[\]+?.,\\\^$|#]/g;
|
|
66
|
-
var commandToRegExp = function commandToRegExp(command) {
|
|
67
|
-
command = command.replace(escapeRegExp, '\\$&').replace(optionalParam, '(?:$1)?').replace(namedParam, function (match, optional) {
|
|
68
|
-
return optional ? match : '([^\\s]+)';
|
|
69
|
-
}).replace(splatParam, '(.*?)').replace(optionalRegex, '\\s*$1?\\s*');
|
|
70
|
-
return new RegExp('^' + command + '$', 'i');
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
// This method receives an array of callbacks to iterate over, and invokes each of them
|
|
74
|
-
var invokeCallbacks = function invokeCallbacks(callbacks) {
|
|
75
|
-
for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
|
|
76
|
-
args[_key - 1] = arguments[_key];
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
callbacks.forEach(function (callback) {
|
|
80
|
-
callback.callback.apply(callback.context, args);
|
|
81
|
-
});
|
|
82
|
-
};
|
|
83
|
-
|
|
84
|
-
var isInitialized = function isInitialized() {
|
|
85
|
-
return recognition !== undefined;
|
|
86
|
-
};
|
|
87
|
-
|
|
88
|
-
// method for logging in developer console when debug mode is on
|
|
89
|
-
var logMessage = function logMessage(text, extraParameters) {
|
|
90
|
-
if (text.indexOf('%c') === -1 && !extraParameters) {
|
|
1
|
+
// src/annyang.ts
|
|
2
|
+
var MIN_RESTART_INTERVAL_MS = 1e3;
|
|
3
|
+
var RESTART_WARNING_INTERVAL = 10;
|
|
4
|
+
var recognition;
|
|
5
|
+
var listening = false;
|
|
6
|
+
var autoRestart = true;
|
|
7
|
+
var debugState = false;
|
|
8
|
+
var debugStyle = "font-weight: bold; color: #00f;";
|
|
9
|
+
var commandsList = /* @__PURE__ */ new Map();
|
|
10
|
+
var callbacks = /* @__PURE__ */ new Map([
|
|
11
|
+
["start", []],
|
|
12
|
+
["error", []],
|
|
13
|
+
["end", []],
|
|
14
|
+
["soundstart", []],
|
|
15
|
+
["result", []],
|
|
16
|
+
["resultMatch", []],
|
|
17
|
+
["resultNoMatch", []],
|
|
18
|
+
["errorNetwork", []],
|
|
19
|
+
["errorPermissionBlocked", []],
|
|
20
|
+
["errorPermissionDenied", []]
|
|
21
|
+
]);
|
|
22
|
+
var lastStartedAt = 0;
|
|
23
|
+
var autoRestartCount = 0;
|
|
24
|
+
var pauseListening = false;
|
|
25
|
+
var optionalParam = /\s*\((.*?)\)\s*/g;
|
|
26
|
+
var optionalRegex = /(\(\?:[^)]+\))\?/g;
|
|
27
|
+
var namedParam = /(\(\?)?:\w+/g;
|
|
28
|
+
var splatParam = /\*\w+/g;
|
|
29
|
+
var escapeRegExp = /[{}[\]+?.\\^$|]/g;
|
|
30
|
+
var commandToRegExp = (command) => {
|
|
31
|
+
const parts = command.split(/([:*]\w+)/);
|
|
32
|
+
const last = parts.length - 1;
|
|
33
|
+
const ending = parts[last].replace(/[.!?]+$/, "");
|
|
34
|
+
const literalEnding = /\S/.test(ending) && (last === 0 || !ending.trimEnd().endsWith(")"));
|
|
35
|
+
if (literalEnding) parts[last] = ending;
|
|
36
|
+
const parsedCommand = parts.map(
|
|
37
|
+
(part, index) => index % 2 ? part : part.replace(escapeRegExp, "\\$&").replace(/([\p{L}\p{N}]),?(?=\s+[\p{L}\p{N}])/gu, "$1,?")
|
|
38
|
+
).join("").replace(optionalParam, "(?:$1)?").replace(namedParam, (match, optional) => {
|
|
39
|
+
return optional ? match : "([^\\s]+)";
|
|
40
|
+
}).replace(splatParam, "(.*?)").replace(optionalRegex, "\\s*$1?\\s*");
|
|
41
|
+
return new RegExp(`^${parsedCommand}${literalEnding ? "[.!?]*" : ""}$`, "iu");
|
|
42
|
+
};
|
|
43
|
+
var getSpeechRecognition = () => globalThis.SpeechRecognition || globalThis.webkitSpeechRecognition;
|
|
44
|
+
var isInitialized = () => {
|
|
45
|
+
return recognition !== void 0;
|
|
46
|
+
};
|
|
47
|
+
var logMessage = (text, extraParameters) => {
|
|
48
|
+
if (debugState) {
|
|
49
|
+
if (text.indexOf("%c") === -1 && !extraParameters) {
|
|
91
50
|
console.log(text);
|
|
92
51
|
} else {
|
|
93
52
|
console.log(text, extraParameters || debugStyle);
|
|
94
53
|
}
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
var registerCommand = (command, callback, originalPhrase) => {
|
|
57
|
+
commandsList.set(originalPhrase, { command, callback });
|
|
58
|
+
logMessage(`Command successfully loaded: %c${originalPhrase}`, debugStyle);
|
|
59
|
+
};
|
|
60
|
+
var invokeCallbacks = (callbacksArr = [], ...args) => {
|
|
61
|
+
callbacksArr.forEach((cb) => {
|
|
62
|
+
cb.callback.apply(cb.context, args);
|
|
63
|
+
});
|
|
64
|
+
};
|
|
65
|
+
var init = () => {
|
|
66
|
+
if (!getSpeechRecognition()) {
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
if (recognition && recognition.abort) {
|
|
70
|
+
recognition.abort();
|
|
71
|
+
}
|
|
72
|
+
recognition = new (getSpeechRecognition())();
|
|
73
|
+
recognition.maxAlternatives = 5;
|
|
74
|
+
recognition.continuous = globalThis.location.protocol === "http:";
|
|
75
|
+
recognition.lang = "en-US";
|
|
76
|
+
recognition.onstart = () => {
|
|
77
|
+
listening = true;
|
|
78
|
+
invokeCallbacks(callbacks.get("start"));
|
|
95
79
|
};
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
if (!isInitialized()) {
|
|
99
|
-
annyang.init({}, false);
|
|
100
|
-
}
|
|
101
|
-
};
|
|
102
|
-
|
|
103
|
-
var registerCommand = function registerCommand(command, callback, originalPhrase) {
|
|
104
|
-
commandsList.push({ command: command, callback: callback, originalPhrase: originalPhrase });
|
|
105
|
-
if (debugState) {
|
|
106
|
-
logMessage('Command successfully loaded: %c' + originalPhrase, debugStyle);
|
|
107
|
-
}
|
|
80
|
+
recognition.onsoundstart = () => {
|
|
81
|
+
invokeCallbacks(callbacks.get("soundstart"));
|
|
108
82
|
};
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
for (var j = 0, l = commandsList.length; j < l; j++) {
|
|
123
|
-
var currentCommand = commandsList[j];
|
|
124
|
-
var result = currentCommand.command.exec(commandText);
|
|
125
|
-
if (result) {
|
|
126
|
-
var parameters = result.slice(1);
|
|
127
|
-
if (debugState) {
|
|
128
|
-
logMessage('command matched: %c' + currentCommand.originalPhrase, debugStyle);
|
|
129
|
-
if (parameters.length) {
|
|
130
|
-
logMessage('with parameters', parameters);
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
// execute the matched command
|
|
134
|
-
currentCommand.callback.apply(this, parameters);
|
|
135
|
-
invokeCallbacks(callbacks.resultMatch, commandText, currentCommand.originalPhrase, results);
|
|
136
|
-
return;
|
|
83
|
+
recognition.onerror = (event) => {
|
|
84
|
+
invokeCallbacks(callbacks.get("error"), event);
|
|
85
|
+
switch (event.error) {
|
|
86
|
+
case "network":
|
|
87
|
+
invokeCallbacks(callbacks.get("errorNetwork"), event);
|
|
88
|
+
break;
|
|
89
|
+
case "not-allowed":
|
|
90
|
+
case "service-not-allowed":
|
|
91
|
+
autoRestart = false;
|
|
92
|
+
if ((/* @__PURE__ */ new Date()).getTime() - lastStartedAt < 200) {
|
|
93
|
+
invokeCallbacks(callbacks.get("errorPermissionBlocked"), event);
|
|
94
|
+
} else {
|
|
95
|
+
invokeCallbacks(callbacks.get("errorPermissionDenied"), event);
|
|
137
96
|
}
|
|
138
|
-
|
|
97
|
+
break;
|
|
98
|
+
default:
|
|
99
|
+
break;
|
|
139
100
|
}
|
|
140
|
-
invokeCallbacks(callbacks.resultNoMatch, results);
|
|
141
101
|
};
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
*
|
|
153
|
-
* // initialize annyang, overwriting any previously added commands
|
|
154
|
-
* annyang.init(commands, true);
|
|
155
|
-
* // adds an additional command without removing the previous commands
|
|
156
|
-
* annyang.init(commands2, false);
|
|
157
|
-
* ````
|
|
158
|
-
* As of v1.1.0 it is no longer required to call init(). Just start() listening whenever you want, and addCommands() whenever, and as often as you like.
|
|
159
|
-
*
|
|
160
|
-
* @param {Object} commands - Commands that annyang should listen to
|
|
161
|
-
* @param {boolean} [resetCommands=true] - Remove all commands before initializing?
|
|
162
|
-
* @method init
|
|
163
|
-
* @deprecated
|
|
164
|
-
* @see [Commands Object](#commands-object)
|
|
165
|
-
*/
|
|
166
|
-
init: function init(commands) {
|
|
167
|
-
var resetCommands = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
|
|
168
|
-
|
|
169
|
-
// Abort previous instances of recognition already running
|
|
170
|
-
if (recognition && recognition.abort) {
|
|
171
|
-
recognition.abort();
|
|
102
|
+
recognition.onend = () => {
|
|
103
|
+
listening = false;
|
|
104
|
+
invokeCallbacks(callbacks.get("end"));
|
|
105
|
+
if (autoRestart) {
|
|
106
|
+
const timeSinceLastStart = (/* @__PURE__ */ new Date()).getTime() - lastStartedAt;
|
|
107
|
+
autoRestartCount += 1;
|
|
108
|
+
if (autoRestartCount % RESTART_WARNING_INTERVAL === 0) {
|
|
109
|
+
logMessage(
|
|
110
|
+
"Speech Recognition is repeatedly stopping and starting. See http://is.gd/annyang_restarts for tips."
|
|
111
|
+
);
|
|
172
112
|
}
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
// Set the max number of alternative transcripts to try and match with a command
|
|
178
|
-
recognition.maxAlternatives = 5;
|
|
179
|
-
|
|
180
|
-
// In HTTPS, turn off continuous mode for faster results.
|
|
181
|
-
// In HTTP, turn on continuous mode for much slower results, but no repeating security notices
|
|
182
|
-
recognition.continuous = root.location.protocol === 'http:';
|
|
183
|
-
|
|
184
|
-
// Sets the language to the default 'en-US'. This can be changed with annyang.setLanguage()
|
|
185
|
-
recognition.lang = 'en-US';
|
|
186
|
-
|
|
187
|
-
recognition.onstart = function () {
|
|
188
|
-
_isListening = true;
|
|
189
|
-
invokeCallbacks(callbacks.start);
|
|
190
|
-
};
|
|
191
|
-
|
|
192
|
-
recognition.onsoundstart = function () {
|
|
193
|
-
invokeCallbacks(callbacks.soundstart);
|
|
194
|
-
};
|
|
195
|
-
|
|
196
|
-
recognition.onerror = function (event) {
|
|
197
|
-
invokeCallbacks(callbacks.error, event);
|
|
198
|
-
switch (event.error) {
|
|
199
|
-
case 'network':
|
|
200
|
-
invokeCallbacks(callbacks.errorNetwork, event);
|
|
201
|
-
break;
|
|
202
|
-
case 'not-allowed':
|
|
203
|
-
case 'service-not-allowed':
|
|
204
|
-
// if permission to use the mic is denied, turn off auto-restart
|
|
205
|
-
autoRestart = false;
|
|
206
|
-
// determine if permission was denied by user or automatically.
|
|
207
|
-
if (new Date().getTime() - lastStartedAt < 200) {
|
|
208
|
-
invokeCallbacks(callbacks.errorPermissionBlocked, event);
|
|
209
|
-
} else {
|
|
210
|
-
invokeCallbacks(callbacks.errorPermissionDenied, event);
|
|
211
|
-
}
|
|
212
|
-
break;
|
|
213
|
-
}
|
|
214
|
-
};
|
|
215
|
-
|
|
216
|
-
recognition.onend = function () {
|
|
217
|
-
_isListening = false;
|
|
218
|
-
invokeCallbacks(callbacks.end);
|
|
219
|
-
// annyang will auto restart if it is closed automatically and not by user action.
|
|
220
|
-
if (autoRestart) {
|
|
221
|
-
// play nicely with the browser, and never restart annyang automatically more than once per second
|
|
222
|
-
var timeSinceLastStart = new Date().getTime() - lastStartedAt;
|
|
223
|
-
autoRestartCount += 1;
|
|
224
|
-
if (autoRestartCount % 10 === 0) {
|
|
225
|
-
if (debugState) {
|
|
226
|
-
logMessage('Speech Recognition is repeatedly stopping and starting. See http://is.gd/annyang_restarts for tips.');
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
if (timeSinceLastStart < 1000) {
|
|
230
|
-
setTimeout(function () {
|
|
231
|
-
annyang.start({ paused: pauseListening });
|
|
232
|
-
}, 1000 - timeSinceLastStart);
|
|
233
|
-
} else {
|
|
234
|
-
annyang.start({ paused: pauseListening });
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
};
|
|
238
|
-
|
|
239
|
-
recognition.onresult = function (event) {
|
|
240
|
-
if (pauseListening) {
|
|
241
|
-
if (debugState) {
|
|
242
|
-
logMessage('Speech heard, but annyang is paused');
|
|
243
|
-
}
|
|
244
|
-
return false;
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
// Map the results to an array
|
|
248
|
-
var SpeechRecognitionResult = event.results[event.resultIndex];
|
|
249
|
-
var results = [];
|
|
250
|
-
for (var k = 0; k < SpeechRecognitionResult.length; k++) {
|
|
251
|
-
results[k] = SpeechRecognitionResult[k].transcript;
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
parseResults(results);
|
|
255
|
-
};
|
|
256
|
-
|
|
257
|
-
// build commands list
|
|
258
|
-
if (resetCommands) {
|
|
259
|
-
commandsList = [];
|
|
260
|
-
}
|
|
261
|
-
if (commands.length) {
|
|
262
|
-
this.addCommands(commands);
|
|
263
|
-
}
|
|
264
|
-
},
|
|
265
|
-
|
|
266
|
-
/**
|
|
267
|
-
* Start listening.
|
|
268
|
-
* It's a good idea to call this after adding some commands first, but not mandatory.
|
|
269
|
-
*
|
|
270
|
-
* Receives an optional options object which supports the following options:
|
|
271
|
-
*
|
|
272
|
-
* - `autoRestart` (boolean, default: true) Should annyang restart itself if it is closed indirectly, because of silence or window conflicts?
|
|
273
|
-
* - `continuous` (boolean) Allow forcing continuous mode on or off. Annyang is pretty smart about this, so only set this if you know what you're doing.
|
|
274
|
-
* - `paused` (boolean, default: true) Start annyang in paused mode.
|
|
275
|
-
*
|
|
276
|
-
* #### Examples:
|
|
277
|
-
* ````javascript
|
|
278
|
-
* // Start listening, don't restart automatically
|
|
279
|
-
* annyang.start({ autoRestart: false });
|
|
280
|
-
* // Start listening, don't restart automatically, stop recognition after first phrase recognized
|
|
281
|
-
* annyang.start({ autoRestart: false, continuous: false });
|
|
282
|
-
* ````
|
|
283
|
-
* @param {Object} [options] - Optional options.
|
|
284
|
-
* @method start
|
|
285
|
-
*/
|
|
286
|
-
start: function start(options) {
|
|
287
|
-
initIfNeeded();
|
|
288
|
-
options = options || {};
|
|
289
|
-
if (options.paused !== undefined) {
|
|
290
|
-
pauseListening = !!options.paused;
|
|
291
|
-
} else {
|
|
292
|
-
pauseListening = false;
|
|
293
|
-
}
|
|
294
|
-
if (options.autoRestart !== undefined) {
|
|
295
|
-
autoRestart = !!options.autoRestart;
|
|
113
|
+
if (timeSinceLastStart < MIN_RESTART_INTERVAL_MS) {
|
|
114
|
+
setTimeout(() => {
|
|
115
|
+
start({ paused: pauseListening });
|
|
116
|
+
}, MIN_RESTART_INTERVAL_MS - timeSinceLastStart);
|
|
296
117
|
} else {
|
|
297
|
-
|
|
118
|
+
start({ paused: pauseListening });
|
|
298
119
|
}
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
recognition.onresult = (event) => {
|
|
123
|
+
if (pauseListening) {
|
|
124
|
+
logMessage("Speech heard, but annyang is paused");
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
const SpeechRecognitionResults = event.results[event.resultIndex];
|
|
128
|
+
const results = Array.from(SpeechRecognitionResults, (result) => result.transcript);
|
|
129
|
+
parseResults(results);
|
|
130
|
+
};
|
|
131
|
+
};
|
|
132
|
+
var initIfNeeded = () => {
|
|
133
|
+
if (!isInitialized()) {
|
|
134
|
+
init();
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
var parseResults = (recognitionResults) => {
|
|
138
|
+
invokeCallbacks(callbacks.get("result"), recognitionResults);
|
|
139
|
+
for (const rawText of recognitionResults) {
|
|
140
|
+
logMessage(`Speech recognized: %c${rawText.trim()}`, debugStyle);
|
|
141
|
+
}
|
|
142
|
+
for (const rawText of recognitionResults) {
|
|
143
|
+
const commandText = rawText.trim();
|
|
144
|
+
for (const [originalPhrase, currentCommand] of commandsList) {
|
|
145
|
+
const matchedCommand = currentCommand.command.exec(commandText);
|
|
146
|
+
if (matchedCommand) {
|
|
147
|
+
const parameters = matchedCommand.slice(1);
|
|
148
|
+
logMessage(`command matched: %c${originalPhrase}`, debugStyle);
|
|
149
|
+
if (parameters.length) {
|
|
150
|
+
logMessage("with parameters", parameters);
|
|
309
151
|
}
|
|
152
|
+
currentCommand.callback(...parameters);
|
|
153
|
+
invokeCallbacks(callbacks.get("resultMatch"), commandText, originalPhrase, recognitionResults);
|
|
154
|
+
return;
|
|
310
155
|
}
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
* ````
|
|
387
|
-
*
|
|
388
|
-
* @param {Object} commands - Commands that annyang should listen to
|
|
389
|
-
* @method addCommands
|
|
390
|
-
* @see [Commands Object](#commands-object)
|
|
391
|
-
*/
|
|
392
|
-
addCommands: function addCommands(commands) {
|
|
393
|
-
var cb;
|
|
394
|
-
|
|
395
|
-
initIfNeeded();
|
|
396
|
-
|
|
397
|
-
for (var phrase in commands) {
|
|
398
|
-
if (commands.hasOwnProperty(phrase)) {
|
|
399
|
-
cb = root[commands[phrase]] || commands[phrase];
|
|
400
|
-
if (typeof cb === 'function') {
|
|
401
|
-
// convert command to regex then register the command
|
|
402
|
-
registerCommand(commandToRegExp(phrase), cb, phrase);
|
|
403
|
-
} else if ((typeof cb === 'undefined' ? 'undefined' : _typeof(cb)) === 'object' && cb.regexp instanceof RegExp) {
|
|
404
|
-
// register the command
|
|
405
|
-
registerCommand(new RegExp(cb.regexp.source, 'i'), cb.callback, phrase);
|
|
406
|
-
} else {
|
|
407
|
-
if (debugState) {
|
|
408
|
-
logMessage('Can not register command: %c' + phrase, debugStyle);
|
|
409
|
-
}
|
|
410
|
-
continue;
|
|
411
|
-
}
|
|
412
|
-
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
invokeCallbacks(callbacks.get("resultNoMatch"), recognitionResults);
|
|
159
|
+
};
|
|
160
|
+
var isSpeechRecognitionSupported = () => !!getSpeechRecognition();
|
|
161
|
+
var addCommands = (commands, resetCommands = false) => {
|
|
162
|
+
if (resetCommands) {
|
|
163
|
+
commandsList.clear();
|
|
164
|
+
}
|
|
165
|
+
for (const phrase of Object.keys(commands)) {
|
|
166
|
+
const cb = commands[phrase];
|
|
167
|
+
if (typeof cb === "function") {
|
|
168
|
+
registerCommand(commandToRegExp(phrase), cb, phrase);
|
|
169
|
+
} else if (typeof cb === "object" && cb.regexp instanceof RegExp) {
|
|
170
|
+
registerCommand(new RegExp(cb.regexp.source, "i"), cb.callback, phrase);
|
|
171
|
+
} else {
|
|
172
|
+
logMessage(`Can not register command: %c${phrase}`, debugStyle);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
};
|
|
176
|
+
var removeCommands = (commandsToRemove) => {
|
|
177
|
+
if (commandsToRemove === void 0) {
|
|
178
|
+
commandsList.clear();
|
|
179
|
+
} else {
|
|
180
|
+
const commandsToRemoveArray = Array.isArray(commandsToRemove) ? commandsToRemove : [commandsToRemove];
|
|
181
|
+
commandsToRemoveArray.forEach((command) => commandsList.delete(command));
|
|
182
|
+
}
|
|
183
|
+
};
|
|
184
|
+
var start = (options = {}) => {
|
|
185
|
+
if (!isSpeechRecognitionSupported()) {
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
initIfNeeded();
|
|
189
|
+
pauseListening = !!options.paused;
|
|
190
|
+
if (options.autoRestart !== void 0) {
|
|
191
|
+
autoRestart = !!options.autoRestart;
|
|
192
|
+
} else {
|
|
193
|
+
autoRestart = true;
|
|
194
|
+
}
|
|
195
|
+
if (options.continuous !== void 0) {
|
|
196
|
+
recognition.continuous = !!options.continuous;
|
|
197
|
+
}
|
|
198
|
+
lastStartedAt = (/* @__PURE__ */ new Date()).getTime();
|
|
199
|
+
try {
|
|
200
|
+
recognition.start();
|
|
201
|
+
} catch (e) {
|
|
202
|
+
logMessage(e instanceof Error ? e.message : String(e));
|
|
203
|
+
}
|
|
204
|
+
};
|
|
205
|
+
var abort = () => {
|
|
206
|
+
autoRestart = false;
|
|
207
|
+
autoRestartCount = 0;
|
|
208
|
+
if (isInitialized()) {
|
|
209
|
+
recognition.abort();
|
|
210
|
+
}
|
|
211
|
+
};
|
|
212
|
+
var pause = () => {
|
|
213
|
+
pauseListening = true;
|
|
214
|
+
};
|
|
215
|
+
var resume = () => {
|
|
216
|
+
start();
|
|
217
|
+
};
|
|
218
|
+
var addCallback = (type, callback, context = void 0) => {
|
|
219
|
+
const callbacksOfType = callbacks.get(type);
|
|
220
|
+
if (typeof callback === "function" && callbacksOfType) {
|
|
221
|
+
const entry = {
|
|
222
|
+
callback,
|
|
223
|
+
context
|
|
224
|
+
};
|
|
225
|
+
callbacksOfType.push(entry);
|
|
226
|
+
return () => {
|
|
227
|
+
const arr = callbacks.get(type);
|
|
228
|
+
if (arr) {
|
|
229
|
+
const idx = arr.indexOf(entry);
|
|
230
|
+
if (idx !== -1) arr.splice(idx, 1);
|
|
413
231
|
}
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
* annyang.removeCommands();
|
|
425
|
-
*
|
|
426
|
-
* // Add some commands
|
|
427
|
-
* annyang.addCommands(commands);
|
|
428
|
-
*
|
|
429
|
-
* // Don't respond to hello
|
|
430
|
-
* annyang.removeCommands('hello');
|
|
431
|
-
*
|
|
432
|
-
* // Don't respond to howdy or hi
|
|
433
|
-
* annyang.removeCommands(['howdy', 'hi']);
|
|
434
|
-
* ````
|
|
435
|
-
* @param {String|Array|Undefined} [commandsToRemove] - Commands to remove
|
|
436
|
-
* @method removeCommands
|
|
437
|
-
*/
|
|
438
|
-
removeCommands: function removeCommands(commandsToRemove) {
|
|
439
|
-
if (commandsToRemove === undefined) {
|
|
440
|
-
commandsList = [];
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
return () => {
|
|
235
|
+
};
|
|
236
|
+
};
|
|
237
|
+
var removeCallback = (type, callback) => {
|
|
238
|
+
callbacks.forEach((callbacksArray, callbackType) => {
|
|
239
|
+
if (type === void 0 || type === callbackType) {
|
|
240
|
+
if (callback === void 0) {
|
|
241
|
+
callbacks.get(callbackType).length = 0;
|
|
441
242
|
} else {
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
return false;
|
|
447
|
-
}
|
|
448
|
-
}
|
|
449
|
-
return true;
|
|
450
|
-
});
|
|
451
|
-
}
|
|
452
|
-
},
|
|
453
|
-
|
|
454
|
-
/**
|
|
455
|
-
* Add a callback function to be called in case one of the following events happens:
|
|
456
|
-
*
|
|
457
|
-
* * `start` - Fired as soon as the browser's Speech Recognition engine starts listening
|
|
458
|
-
* * `soundstart` - Fired as soon as any sound (possibly speech) has been detected.
|
|
459
|
-
* This will fire once per Speech Recognition starting. See https://is.gd/annyang_sound_start
|
|
460
|
-
* * `error` - Fired when the browser's Speech Recogntion engine returns an error, this generic error callback will be followed by more accurate error callbacks (both will fire if both are defined)
|
|
461
|
-
* Callback function will be called with the error event as the first argument
|
|
462
|
-
* * `errorNetwork` - Fired when Speech Recognition fails because of a network error
|
|
463
|
-
* Callback function will be called with the error event as the first argument
|
|
464
|
-
* * `errorPermissionBlocked` - Fired when the browser blocks the permission request to use Speech Recognition.
|
|
465
|
-
* Callback function will be called with the error event as the first argument
|
|
466
|
-
* * `errorPermissionDenied` - Fired when the user blocks the permission request to use Speech Recognition.
|
|
467
|
-
* Callback function will be called with the error event as the first argument
|
|
468
|
-
* * `end` - Fired when the browser's Speech Recognition engine stops
|
|
469
|
-
* * `result` - Fired as soon as some speech was identified. This generic callback will be followed by either the `resultMatch` or `resultNoMatch` callbacks.
|
|
470
|
-
* Callback functions for to this event will be called with an array of possible phrases the user said as the first argument
|
|
471
|
-
* * `resultMatch` - Fired when annyang was able to match between what the user said and a registered command
|
|
472
|
-
* Callback functions for this event will be called with three arguments in the following order:
|
|
473
|
-
* * The phrase the user said that matched a command
|
|
474
|
-
* * The command that was matched
|
|
475
|
-
* * An array of possible alternative phrases the user might have said
|
|
476
|
-
* * `resultNoMatch` - Fired when what the user said didn't match any of the registered commands.
|
|
477
|
-
* Callback functions for this event will be called with an array of possible phrases the user might've said as the first argument
|
|
478
|
-
*
|
|
479
|
-
* #### Examples:
|
|
480
|
-
* ````javascript
|
|
481
|
-
* annyang.addCallback('error', function() {
|
|
482
|
-
* $('.myErrorText').text('There was an error!');
|
|
483
|
-
* });
|
|
484
|
-
*
|
|
485
|
-
* annyang.addCallback('resultMatch', function(userSaid, commandText, phrases) {
|
|
486
|
-
* console.log(userSaid); // sample output: 'hello'
|
|
487
|
-
* console.log(commandText); // sample output: 'hello (there)'
|
|
488
|
-
* console.log(phrases); // sample output: ['hello', 'halo', 'yellow', 'polo', 'hello kitty']
|
|
489
|
-
* });
|
|
490
|
-
*
|
|
491
|
-
* // pass local context to a global function called notConnected
|
|
492
|
-
* annyang.addCallback('errorNetwork', notConnected, this);
|
|
493
|
-
* ````
|
|
494
|
-
* @param {String} type - Name of event that will trigger this callback
|
|
495
|
-
* @param {Function} callback - The function to call when event is triggered
|
|
496
|
-
* @param {Object} [context] - Optional context for the callback function
|
|
497
|
-
* @method addCallback
|
|
498
|
-
*/
|
|
499
|
-
addCallback: function addCallback(type, callback, context) {
|
|
500
|
-
var cb = root[callback] || callback;
|
|
501
|
-
if (typeof cb === 'function' && callbacks[type] !== undefined) {
|
|
502
|
-
callbacks[type].push({ callback: cb, context: context || this });
|
|
503
|
-
}
|
|
504
|
-
},
|
|
505
|
-
|
|
506
|
-
/**
|
|
507
|
-
* Remove callbacks from events.
|
|
508
|
-
*
|
|
509
|
-
* - Pass an event name and a callback command to remove that callback command from that event type.
|
|
510
|
-
* - Pass just an event name to remove all callback commands from that event type.
|
|
511
|
-
* - Pass undefined as event name and a callback command to remove that callback command from all event types.
|
|
512
|
-
* - Pass no params to remove all callback commands from all event types.
|
|
513
|
-
*
|
|
514
|
-
* #### Examples:
|
|
515
|
-
* ````javascript
|
|
516
|
-
* annyang.addCallback('start', myFunction1);
|
|
517
|
-
* annyang.addCallback('start', myFunction2);
|
|
518
|
-
* annyang.addCallback('end', myFunction1);
|
|
519
|
-
* annyang.addCallback('end', myFunction2);
|
|
520
|
-
*
|
|
521
|
-
* // Remove all callbacks from all events:
|
|
522
|
-
* annyang.removeCallback();
|
|
523
|
-
*
|
|
524
|
-
* // Remove all callbacks attached to end event:
|
|
525
|
-
* annyang.removeCallback('end');
|
|
526
|
-
*
|
|
527
|
-
* // Remove myFunction2 from being called on start:
|
|
528
|
-
* annyang.removeCallback('start', myFunction2);
|
|
529
|
-
*
|
|
530
|
-
* // Remove myFunction1 from being called on all events:
|
|
531
|
-
* annyang.removeCallback(undefined, myFunction1);
|
|
532
|
-
* ````
|
|
533
|
-
*
|
|
534
|
-
* @param type Name of event type to remove callback from
|
|
535
|
-
* @param callback The callback function to remove
|
|
536
|
-
* @returns undefined
|
|
537
|
-
* @method removeCallback
|
|
538
|
-
*/
|
|
539
|
-
removeCallback: function removeCallback(type, callback) {
|
|
540
|
-
var compareWithCallbackParameter = function compareWithCallbackParameter(cb) {
|
|
541
|
-
return cb.callback !== callback;
|
|
542
|
-
};
|
|
543
|
-
// Go over each callback type in callbacks store object
|
|
544
|
-
for (var callbackType in callbacks) {
|
|
545
|
-
if (callbacks.hasOwnProperty(callbackType)) {
|
|
546
|
-
// if this is the type user asked to delete, or he asked to delete all, go ahead.
|
|
547
|
-
if (type === undefined || type === callbackType) {
|
|
548
|
-
// If user asked to delete all callbacks in this type or all types
|
|
549
|
-
if (callback === undefined) {
|
|
550
|
-
callbacks[callbackType] = [];
|
|
551
|
-
} else {
|
|
552
|
-
// Remove all matching callbacks
|
|
553
|
-
callbacks[callbackType] = callbacks[callbackType].filter(compareWithCallbackParameter);
|
|
554
|
-
}
|
|
555
|
-
}
|
|
556
|
-
}
|
|
243
|
+
callbacks.set(
|
|
244
|
+
callbackType,
|
|
245
|
+
callbacksArray.filter((cb) => cb.callback !== callback)
|
|
246
|
+
);
|
|
557
247
|
}
|
|
558
|
-
},
|
|
559
|
-
|
|
560
|
-
/**
|
|
561
|
-
* Returns true if speech recognition is currently on.
|
|
562
|
-
* Returns false if speech recognition is off or annyang is paused.
|
|
563
|
-
*
|
|
564
|
-
* @return boolean true = SpeechRecognition is on and annyang is listening
|
|
565
|
-
* @method isListening
|
|
566
|
-
*/
|
|
567
|
-
isListening: function isListening() {
|
|
568
|
-
return _isListening && !pauseListening;
|
|
569
|
-
},
|
|
570
|
-
|
|
571
|
-
/**
|
|
572
|
-
* Returns the instance of the browser's SpeechRecognition object used by annyang.
|
|
573
|
-
* Useful in case you want direct access to the browser's Speech Recognition engine.
|
|
574
|
-
*
|
|
575
|
-
* @returns SpeechRecognition The browser's Speech Recognizer currently used by annyang
|
|
576
|
-
* @method getSpeechRecognizer
|
|
577
|
-
*/
|
|
578
|
-
getSpeechRecognizer: function getSpeechRecognizer() {
|
|
579
|
-
return recognition;
|
|
580
|
-
},
|
|
581
|
-
|
|
582
|
-
/**
|
|
583
|
-
* Simulate speech being recognized. This will trigger the same events and behavior as when the Speech Recognition
|
|
584
|
-
* detects speech.
|
|
585
|
-
*
|
|
586
|
-
* Can accept either a string containing a single sentence, or an array containing multiple sentences to be checked
|
|
587
|
-
* in order until one of them matches a command (similar to the way Speech Recognition Alternatives are parsed)
|
|
588
|
-
*
|
|
589
|
-
* #### Examples:
|
|
590
|
-
* ````javascript
|
|
591
|
-
* annyang.trigger('Time for some thrilling heroics');
|
|
592
|
-
* annyang.trigger(
|
|
593
|
-
* ['Time for some thrilling heroics', 'Time for some thrilling aerobics']
|
|
594
|
-
* );
|
|
595
|
-
* ````
|
|
596
|
-
*
|
|
597
|
-
* @param string|array sentences A sentence as a string or an array of strings of possible sentences
|
|
598
|
-
* @returns undefined
|
|
599
|
-
* @method trigger
|
|
600
|
-
*/
|
|
601
|
-
trigger: function trigger(sentences) {
|
|
602
|
-
if (!annyang.isListening()) {
|
|
603
|
-
if (debugState) {
|
|
604
|
-
if (!_isListening) {
|
|
605
|
-
logMessage('Cannot trigger while annyang is aborted');
|
|
606
|
-
} else {
|
|
607
|
-
logMessage('Speech heard, but annyang is paused');
|
|
608
|
-
}
|
|
609
|
-
}
|
|
610
|
-
return;
|
|
611
|
-
}
|
|
612
|
-
|
|
613
|
-
if (!Array.isArray(sentences)) {
|
|
614
|
-
sentences = [sentences];
|
|
615
|
-
}
|
|
616
|
-
|
|
617
|
-
parseResults(sentences);
|
|
618
248
|
}
|
|
619
|
-
};
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
249
|
+
});
|
|
250
|
+
};
|
|
251
|
+
var isListening = () => {
|
|
252
|
+
return listening && !pauseListening;
|
|
253
|
+
};
|
|
254
|
+
var getState = () => {
|
|
255
|
+
if (!listening) return "idle";
|
|
256
|
+
if (pauseListening) return "paused";
|
|
257
|
+
return "listening";
|
|
258
|
+
};
|
|
259
|
+
var setLanguage = (language) => {
|
|
260
|
+
if (!isSpeechRecognitionSupported()) {
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
initIfNeeded();
|
|
264
|
+
recognition.lang = language;
|
|
265
|
+
};
|
|
266
|
+
var debug = (newState = true) => {
|
|
267
|
+
debugState = !!newState;
|
|
268
|
+
};
|
|
269
|
+
var trigger = (sentences = []) => {
|
|
270
|
+
parseResults(Array.isArray(sentences) ? sentences : [sentences]);
|
|
271
|
+
};
|
|
272
|
+
var getSpeechRecognizer = () => {
|
|
273
|
+
return recognition;
|
|
274
|
+
};
|
|
275
|
+
var initDeprecated = () => {
|
|
276
|
+
console.warn(
|
|
277
|
+
"annyang.init() is deprecated and no longer needed. annyang initializes automatically on start() or addCommands(). Remove this call."
|
|
278
|
+
);
|
|
279
|
+
};
|
|
280
|
+
var annyang = {
|
|
281
|
+
isSpeechRecognitionSupported,
|
|
282
|
+
addCommands,
|
|
283
|
+
removeCommands,
|
|
284
|
+
start,
|
|
285
|
+
abort,
|
|
286
|
+
pause,
|
|
287
|
+
resume,
|
|
288
|
+
addCallback,
|
|
289
|
+
removeCallback,
|
|
290
|
+
isListening,
|
|
291
|
+
setLanguage,
|
|
292
|
+
trigger,
|
|
293
|
+
debug,
|
|
294
|
+
getSpeechRecognizer,
|
|
295
|
+
getState,
|
|
296
|
+
init: initDeprecated,
|
|
297
|
+
get state() {
|
|
298
|
+
return getState();
|
|
299
|
+
}
|
|
300
|
+
};
|
|
301
|
+
var annyang_default = annyang;
|
|
302
|
+
export {
|
|
303
|
+
abort,
|
|
304
|
+
addCallback,
|
|
305
|
+
addCommands,
|
|
306
|
+
debug,
|
|
307
|
+
annyang_default as default,
|
|
308
|
+
getSpeechRecognizer,
|
|
309
|
+
getState,
|
|
310
|
+
initDeprecated as init,
|
|
311
|
+
isListening,
|
|
312
|
+
isSpeechRecognitionSupported,
|
|
313
|
+
pause,
|
|
314
|
+
removeCallback,
|
|
315
|
+
removeCommands,
|
|
316
|
+
resume,
|
|
317
|
+
setLanguage,
|
|
318
|
+
start,
|
|
319
|
+
trigger
|
|
320
|
+
};
|
|
321
|
+
//# sourceMappingURL=annyang.js.map
|