web-speech-cognitive-services
Advanced tools
Comparing version 5.0.2-master.e668a0d to 5.0.2-master.e85a10c
@@ -9,6 +9,21 @@ # Changelog | ||
### Changed | ||
### Breaking changes | ||
- `playground`: Add delayed start to playground for testing speech recognition initiated outside of user gestures, in PR [#78](https://github.com/compulim/web-speech-congitive-services/pull/78) | ||
#### Unifying options to pass credentials | ||
`authorizationToken`, `region`, and `subscriptionKey` are being deprecated in favor of `credentials` options. `credentials` can be one of the following types: | ||
- `{ authorizationToken: string, region: string? }` | ||
- `{ region: string?, subscriptionKey: string }` | ||
- `Promise<{ authorizationToken: string, region: string? }>` | ||
- `Promise<{ region: string?, subscriptionKey: string }>` | ||
- `() => { authorizationToken: string, region: string? }` | ||
- `() => { region: string?, subscriptionKey: string }` | ||
- `() => Promise<{ authorizationToken: string, region: string? }>` | ||
- `() => Promise<{ region: string?, subscriptionKey: string }>` | ||
If `credentials` is a function, it will be called just before the credentials is needed and may be called very frequently. This behavior matches the deprecating `authorizationToken`. The result of the call is also expected to be cached. | ||
If `region` is not returned, the default value of `"westus"` will be used. | ||
### Fixed | ||
@@ -18,6 +33,20 @@ | ||
### Removed | ||
- 🔥 `authorizationToken`, `region`, and `subscriptionKey` are being deprecated in favor of `credentials` options, by [@compulim](https://github.com/compulim) in PR [#80](https://github.com/compulim/web-speech-cognitive-services/pull/80) | ||
### Added | ||
- Speech recognition: New `loosenEvents` option, default is `false`. When enabled, we will no longer follow observed browser event order. We will send finalized `result` event as early as possible. This will not break conformance to W3C specifications. By [@compulim](https://github.com/compulim), in PR [#79](https://github.com/compulim/web-speech-cognitive-services/pull/79) | ||
- `playground`: Add delayed start to playground for testing speech recognition initiated outside of user gestures, in PR [#78](https://github.com/compulim/web-speech-congitive-services/pull/78) | ||
- Speech recognition: New `looseEvents` option, default is `false`. When enabled, we will no longer follow observed browser event order. We will send finalized `result` event as early as possible. This will not break conformance to W3C specifications. By [@compulim](https://github.com/compulim), in PR [#79](https://github.com/compulim/web-speech-cognitive-services/pull/79) | ||
- Speech recognition: Create ponyfill using `SpeechRecognizer` object from [`microsoft-cognitiveservices-speech-sdk`](https://npmjs.com/package/microsoft-cognitiveservices-speech-sdk), by [@compulim](https://github.com/compulim), in PR [#73](https://github.com/compulim/web-speech-cognitive-services/pull/73) | ||
- `credentials` option is added for obtaining authorization token and region, or subscription key and region, in a single object or function call, by [@compulim](https://github.com/compulim) in PR [#80](https://github.com/compulim/web-speech-cognitive-services/pull/80) | ||
### Changed | ||
- Bumped dependencies, in PR [#73](https://github.com/compulim/web-speech-cognitive-services/pull/73) | ||
- [babel-jest@^24.9.0](https://www.npmjs.com/package/babel-jest) | ||
- [jest@^24.9.0](https://www.npmjs.com/package/jest) | ||
- [rimraf@^3.0.0](https://www.npmjs.com/package/rimraf) | ||
## [5.0.1] - 2019-10-25 | ||
@@ -24,0 +53,0 @@ |
@@ -46,3 +46,3 @@ "use strict"; | ||
var VERSION = "5.0.2-master.e668a0d"; | ||
var VERSION = "5.0.2-master.e85a10c"; | ||
@@ -49,0 +49,0 @@ function buildSpeechResult(transcript, confidence, isFinal) { |
"use strict"; | ||
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard"); | ||
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); | ||
@@ -15,2 +17,8 @@ | ||
}); | ||
Object.defineProperty(exports, "createSpeechRecognitionPonyfillFromRecognizer", { | ||
enumerable: true, | ||
get: function get() { | ||
return _SpeechToText.createSpeechRecognitionPonyfillFromRecognizer; | ||
} | ||
}); | ||
Object.defineProperty(exports, "createSpeechSynthesisPonyfill", { | ||
@@ -31,3 +39,3 @@ enumerable: true, | ||
var _SpeechToText = _interopRequireDefault(require("./SpeechServices/SpeechToText")); | ||
var _SpeechToText = _interopRequireWildcard(require("./SpeechServices/SpeechToText")); | ||
@@ -42,12 +50,5 @@ var _TextToSpeech = _interopRequireDefault(require("./SpeechServices/TextToSpeech")); | ||
var shouldWarnOnSubscriptionKey = true; | ||
function createSpeechServicesPonyfill() { | ||
var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; | ||
if (shouldWarnOnSubscriptionKey && options.subscriptionKey) { | ||
console.warn('web-speech-cognitive-services: In production environment, subscription key should not be used, authorization token should be used instead.'); | ||
shouldWarnOnSubscriptionKey = false; | ||
} | ||
for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { | ||
@@ -69,4 +70,4 @@ args[_key - 1] = arguments[_key]; | ||
meta.setAttribute('name', 'web-speech-cognitive-services'); | ||
meta.setAttribute('content', "version=".concat("5.0.2-master.e668a0d")); | ||
meta.setAttribute('content', "version=".concat("5.0.2-master.e85a10c")); | ||
document.head.appendChild(meta); | ||
//# sourceMappingURL=SpeechServices.js.map |
"use strict"; | ||
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); | ||
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard"); | ||
@@ -8,5 +8,11 @@ Object.defineProperty(exports, "__esModule", { | ||
}); | ||
Object.defineProperty(exports, "createSpeechRecognitionPonyfillFromRecognizer", { | ||
enumerable: true, | ||
get: function get() { | ||
return _createSpeechRecognitionPonyfill.createSpeechRecognitionPonyfillFromRecognizer; | ||
} | ||
}); | ||
exports.default = void 0; | ||
var _createSpeechRecognitionPonyfill = _interopRequireDefault(require("./SpeechToText/createSpeechRecognitionPonyfill")); | ||
var _createSpeechRecognitionPonyfill = _interopRequireWildcard(require("./SpeechToText/createSpeechRecognitionPonyfill")); | ||
@@ -13,0 +19,0 @@ var _default = _createSpeechRecognitionPonyfill.default; |
@@ -25,9 +25,15 @@ "use strict"; | ||
if (result.reason === RecognizingSpeech) { | ||
return [{ | ||
if (result.reason === RecognizingSpeech || result.reason === RecognizedSpeech && !result.json.NBest) { | ||
var resultList = [{ | ||
confidence: .5, | ||
transcript: result.text | ||
}]; | ||
if (result.reason === RecognizedSpeech) { | ||
resultList.isFinal = true; | ||
} | ||
return resultList; | ||
} else if (result.reason === RecognizedSpeech) { | ||
var resultList = (0, _arrayToMap.default)((result.json.NBest || []).slice(0, maxAlternatives).map(function (_ref2) { | ||
var _resultList = (0, _arrayToMap.default)((result.json.NBest || []).slice(0, maxAlternatives).map(function (_ref2) { | ||
var confidence = _ref2.Confidence, | ||
@@ -45,3 +51,4 @@ display = _ref2.Display, | ||
}); | ||
return resultList; | ||
return _resultList; | ||
} | ||
@@ -48,0 +55,0 @@ |
@@ -8,8 +8,9 @@ "use strict"; | ||
}); | ||
exports.createSpeechRecognitionPonyfillFromRecognizer = createSpeechRecognitionPonyfillFromRecognizer; | ||
exports.default = void 0; | ||
var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator")); | ||
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray")); | ||
var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator")); | ||
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator")); | ||
@@ -35,2 +36,4 @@ | ||
var _patchOptions2 = _interopRequireDefault(require("../patchOptions")); | ||
var _SpeechGrammarList = _interopRequireDefault(require("./SpeechGrammarList")); | ||
@@ -135,40 +138,9 @@ | ||
var _default = function _default() { | ||
var _ref3 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, | ||
_ref3$audioConfig = _ref3.audioConfig, | ||
audioConfig = _ref3$audioConfig === void 0 ? AudioConfig.fromDefaultMicrophoneInput() : _ref3$audioConfig, | ||
authorizationToken = _ref3.authorizationToken, | ||
_ref3$enableTelemetry = _ref3.enableTelemetry, | ||
enableTelemetry = _ref3$enableTelemetry === void 0 ? true : _ref3$enableTelemetry, | ||
looseEvent = _ref3.looseEvent, | ||
looseEvents = _ref3.looseEvents, | ||
referenceGrammars = _ref3.referenceGrammars, | ||
_ref3$region = _ref3.region, | ||
region = _ref3$region === void 0 ? 'westus' : _ref3$region, | ||
speechRecognitionEndpointId = _ref3.speechRecognitionEndpointId, | ||
subscriptionKey = _ref3.subscriptionKey, | ||
_ref3$strictEventOrde = _ref3.strictEventOrder, | ||
strictEventOrder = _ref3$strictEventOrde === void 0 ? true : _ref3$strictEventOrde, | ||
_ref3$textNormalizati = _ref3.textNormalization, | ||
textNormalization = _ref3$textNormalizati === void 0 ? 'display' : _ref3$textNormalizati; | ||
if (!authorizationToken && !subscriptionKey) { | ||
console.warn('web-speech-cognitive-services: Either authorizationToken or subscriptionKey must be specified'); | ||
return {}; | ||
} else if (!window.navigator.mediaDevices || !window.navigator.mediaDevices.getUserMedia) { | ||
console.warn('web-speech-cognitive-services: This browser does not support WebRTC and it will not work with Cognitive Services Speech Services.'); | ||
return {}; | ||
} | ||
if (typeof looseEvent !== 'undefined') { | ||
console.warn('web-speech-cognitive-services: The option "looseEvent" should be named as "looseEvents".'); | ||
looseEvents = looseEvent; | ||
} | ||
var _onAudibleChunk; | ||
function prepareAudioConfig(audioConfig) { | ||
var originalAttach = audioConfig.attach; | ||
var firstChunk; | ||
var muted; // We modify "attach" function and detect when audible chunk is read. | ||
// We will only modify "attach" function once. | ||
audioConfig.attach = improviseAsync(audioConfig.attach.bind(audioConfig), function (reader) { | ||
audioConfig.attach = improviseAsync(originalAttach.bind(audioConfig), function (reader) { | ||
return _objectSpread({}, reader, { | ||
@@ -179,6 +151,9 @@ read: improviseAsync(reader.read.bind(reader), function (chunk) { | ||
// 2. Observe the amplitude (100-110) for the first few chunks | ||
// (This is short static caught when turning on the microphone) | ||
// (There is a short static caught when turning on the microphone) | ||
// 3. Set the number a bit higher than the observation | ||
if (averageAmplitude(chunk.buffer) > 150) { | ||
_onAudibleChunk && _onAudibleChunk(); | ||
if (!firstChunk && averageAmplitude(chunk.buffer) > 150) { | ||
audioConfig.events.onEvent({ | ||
name: 'FirstAudibleChunk' | ||
}); | ||
firstChunk = true; | ||
} | ||
@@ -197,4 +172,21 @@ | ||
}); | ||
}); // If enableTelemetry is set to null or non-boolean, we will default to true. | ||
}); | ||
return { | ||
audioConfig: audioConfig, | ||
pause: function pause() { | ||
muted = true; | ||
}, | ||
unprepare: function unprepare() { | ||
audioConfig.attach = originalAttach; | ||
} | ||
}; | ||
} | ||
function createSpeechRecognitionPonyfillFromRecognizer(_ref3) { | ||
var createRecognizer = _ref3.createRecognizer, | ||
enableTelemetry = _ref3.enableTelemetry, | ||
looseEvents = _ref3.looseEvents, | ||
referenceGrammars = _ref3.referenceGrammars, | ||
textNormalization = _ref3.textNormalization; | ||
// If enableTelemetry is set to null or non-boolean, we will default to true. | ||
SpeechRecognizer.enableTelemetry(enableTelemetry !== false); | ||
@@ -221,75 +213,2 @@ | ||
(0, _createClass2.default)(SpeechRecognition, [{ | ||
key: "createRecognizer", | ||
value: function () { | ||
var _createRecognizer = (0, _asyncToGenerator2.default)( | ||
/*#__PURE__*/ | ||
_regenerator.default.mark(function _callee() { | ||
var speechConfig; | ||
return _regenerator.default.wrap(function _callee$(_context) { | ||
while (1) { | ||
switch (_context.prev = _context.next) { | ||
case 0: | ||
if (!authorizationToken) { | ||
_context.next = 16; | ||
break; | ||
} | ||
_context.t1 = SpeechConfig; | ||
if (!(typeof authorizationToken === 'function')) { | ||
_context.next = 8; | ||
break; | ||
} | ||
_context.next = 5; | ||
return authorizationToken(); | ||
case 5: | ||
_context.t2 = _context.sent; | ||
_context.next = 11; | ||
break; | ||
case 8: | ||
_context.next = 10; | ||
return authorizationToken; | ||
case 10: | ||
_context.t2 = _context.sent; | ||
case 11: | ||
_context.t3 = _context.t2; | ||
_context.t4 = region; | ||
_context.t0 = _context.t1.fromAuthorizationToken.call(_context.t1, _context.t3, _context.t4); | ||
_context.next = 17; | ||
break; | ||
case 16: | ||
_context.t0 = SpeechConfig.fromSubscription(subscriptionKey, region); | ||
case 17: | ||
speechConfig = _context.t0; | ||
if (speechRecognitionEndpointId) { | ||
speechConfig.endpointId = speechRecognitionEndpointId; | ||
} | ||
speechConfig.outputFormat = OutputFormat.Detailed; | ||
speechConfig.speechRecognitionLanguage = this.lang || 'en-US'; | ||
return _context.abrupt("return", new SpeechRecognizer(speechConfig, audioConfig)); | ||
case 22: | ||
case "end": | ||
return _context.stop(); | ||
} | ||
} | ||
}, _callee, this); | ||
})); | ||
function createRecognizer() { | ||
return _createRecognizer.apply(this, arguments); | ||
} | ||
return createRecognizer; | ||
}() | ||
}, { | ||
key: "emitCognitiveServices", | ||
@@ -323,26 +242,19 @@ value: function emitCognitiveServices(type, event) { | ||
/*#__PURE__*/ | ||
_regenerator.default.mark(function _callee2() { | ||
_regenerator.default.mark(function _callee() { | ||
var _this3 = this; | ||
var recognizer, queue, soundStarted, speechStarted, stopping, _recognizer$audioConf, detachAudioConfigEvent, phrases, dynamicGrammar, audioStarted, finalEvent, finalizedResults, _loop, loop, _ret; | ||
var recognizer, _prepareAudioConfig, pause, unprepare, queue, soundStarted, speechStarted, stopping, _recognizer$audioConf, detachAudioConfigEvent, phrases, dynamicGrammar, audioStarted, finalEvent, finalizedResults, _loop, loop, _ret; | ||
return _regenerator.default.wrap(function _callee2$(_context3) { | ||
return _regenerator.default.wrap(function _callee$(_context2) { | ||
while (1) { | ||
switch (_context3.prev = _context3.next) { | ||
switch (_context2.prev = _context2.next) { | ||
case 0: | ||
_context3.next = 2; | ||
return this.createRecognizer(); | ||
_context2.next = 2; | ||
return createRecognizer(this.lang); | ||
case 2: | ||
recognizer = _context3.sent; | ||
recognizer = _context2.sent; | ||
_prepareAudioConfig = prepareAudioConfig(recognizer.audioConfig), pause = _prepareAudioConfig.pause, unprepare = _prepareAudioConfig.unprepare; | ||
_context2.prev = 4; | ||
queue = (0, _createPromiseQueue.default)(); | ||
muted = false; | ||
_onAudibleChunk = function onAudibleChunk() { | ||
queue.push({ | ||
firstAudibleChunk: {} | ||
}); | ||
_onAudibleChunk = null; | ||
}; | ||
_recognizer$audioConf = recognizer.audioConfig.events.attach(function (event) { | ||
@@ -359,2 +271,6 @@ var name = event.name; | ||
}); | ||
} else if (name === 'FirstAudibleChunk') { | ||
queue.push({ | ||
firstAudibleChunk: {} | ||
}); | ||
} | ||
@@ -437,2 +353,3 @@ }), detachAudioConfigEvent = _recognizer$audioConf.detach; | ||
// "speechEndDetected" is never fired, probably because we are using startContinuousRecognitionAsync instead of recognizeOnceAsync. | ||
// Update: "speechEndDetected" is fired for DLSpeech.listenOnceAsync() | ||
queue.push({ | ||
@@ -450,3 +367,3 @@ speechEndDetected: { | ||
phrases && phrases.length && dynamicGrammar.addPhrase(phrases); | ||
_context3.next = 20; | ||
_context2.next = 20; | ||
return cognitiveServicesAsyncToPromise(recognizer.startContinuousRecognitionAsync.bind(recognizer))(); | ||
@@ -472,11 +389,11 @@ | ||
var event, abort, audioSourceOff, audioSourceReady, canceled, firstAudibleChunk, recognized, recognizing, stop, errorMessage, result, recognizable; | ||
return _regenerator.default.wrap(function _loop$(_context2) { | ||
return _regenerator.default.wrap(function _loop$(_context) { | ||
while (1) { | ||
switch (_context2.prev = _context2.next) { | ||
switch (_context.prev = _context.next) { | ||
case 0: | ||
_context2.next = 2; | ||
_context.next = 2; | ||
return queue.shift(); | ||
case 2: | ||
event = _context2.sent; | ||
event = _context.sent; | ||
abort = event.abort, audioSourceOff = event.audioSourceOff, audioSourceReady = event.audioSourceReady, canceled = event.canceled, firstAudibleChunk = event.firstAudibleChunk, recognized = event.recognized, recognizing = event.recognizing, stop = event.stop; // We are emitting event "cognitiveservices" for debugging purpose. | ||
@@ -490,3 +407,3 @@ | ||
if (!/Permission[\t-\r \xA0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF]denied/.test(errorMessage || '')) { | ||
_context2.next = 9; | ||
_context.next = 9; | ||
break; | ||
@@ -500,3 +417,3 @@ } | ||
}; | ||
return _context2.abrupt("return", "break"); | ||
return _context.abrupt("return", "break"); | ||
@@ -509,3 +426,3 @@ case 9: | ||
if (!errorMessage) { | ||
_context2.next = 15; | ||
_context.next = 15; | ||
break; | ||
@@ -532,7 +449,7 @@ } | ||
return _context2.abrupt("return", "break"); | ||
return _context.abrupt("return", "break"); | ||
case 15: | ||
if (!(abort || stop)) { | ||
_context2.next = 23; | ||
_context.next = 22; | ||
break; | ||
@@ -545,25 +462,26 @@ } | ||
type: 'error' | ||
}; | ||
}; // If we are aborting, we will ignore lingering recognizing/recognized events. But if we are stopping, we need them. | ||
stopping = 'abort'; | ||
} else { | ||
// When we set to mute and { isEnd: true }, Speech Services will send us "recognized" event. | ||
muted = true; | ||
// When we pause, we will send { isEnd: true }, Speech Services will send us "recognized" event. | ||
pause(); | ||
stopping = 'stop'; | ||
} | ||
stopping = true; | ||
if (!abort) { | ||
_context2.next = 21; | ||
_context.next = 20; | ||
break; | ||
} | ||
_context2.next = 21; | ||
_context.next = 20; | ||
return cognitiveServicesAsyncToPromise(recognizer.stopContinuousRecognitionAsync.bind(recognizer))(); | ||
case 21: | ||
_context2.next = 43; | ||
case 20: | ||
_context.next = 61; | ||
break; | ||
case 23: | ||
case 22: | ||
if (!audioSourceReady) { | ||
_context2.next = 28; | ||
_context.next = 27; | ||
break; | ||
@@ -575,8 +493,8 @@ } | ||
audioStarted = true; | ||
_context2.next = 43; | ||
_context.next = 61; | ||
break; | ||
case 28: | ||
case 27: | ||
if (!firstAudibleChunk) { | ||
_context2.next = 33; | ||
_context.next = 32; | ||
break; | ||
@@ -588,12 +506,14 @@ } | ||
soundStarted = true; | ||
_context2.next = 43; | ||
_context.next = 61; | ||
break; | ||
case 33: | ||
case 32: | ||
if (!audioSourceOff) { | ||
_context2.next = 42; | ||
_context.next = 40; | ||
break; | ||
} | ||
stopping = true; | ||
// Looks like we don't need this line and all the tests are still working. | ||
// Guessing probably stopping is already truthy. | ||
// stopping = true; | ||
speechStarted && _this3.dispatchEvent(new SpeechRecognitionEvent('speechend')); | ||
@@ -603,78 +523,108 @@ soundStarted && _this3.dispatchEvent(new SpeechRecognitionEvent('soundend')); | ||
audioStarted = soundStarted = speechStarted = false; | ||
return _context2.abrupt("return", "break"); | ||
return _context.abrupt("return", "break"); | ||
case 42: | ||
if (recognized && recognized.result && recognized.result.reason === ResultReason.NoMatch) { | ||
finalEvent = { | ||
error: 'no-speech', | ||
type: 'error' | ||
}; | ||
} else if (recognized || recognizing) { | ||
if (!audioStarted) { | ||
// Unconfirmed prevention of quirks | ||
_this3.dispatchEvent(new SpeechRecognitionEvent('audiostart')); | ||
case 40: | ||
if (!(stopping !== 'abort')) { | ||
_context.next = 61; | ||
break; | ||
} | ||
audioStarted = true; | ||
} | ||
if (!(recognized && recognized.result && recognized.result.reason === ResultReason.NoMatch)) { | ||
_context.next = 45; | ||
break; | ||
} | ||
if (!soundStarted) { | ||
_this3.dispatchEvent(new SpeechRecognitionEvent('soundstart')); | ||
finalEvent = { | ||
error: 'no-speech', | ||
type: 'error' | ||
}; | ||
_context.next = 61; | ||
break; | ||
soundStarted = true; | ||
} | ||
case 45: | ||
if (!(recognized || recognizing)) { | ||
_context.next = 61; | ||
break; | ||
} | ||
if (!speechStarted) { | ||
_this3.dispatchEvent(new SpeechRecognitionEvent('speechstart')); | ||
if (!audioStarted) { | ||
// Unconfirmed prevention of quirks | ||
_this3.dispatchEvent(new SpeechRecognitionEvent('audiostart')); | ||
speechStarted = true; | ||
} | ||
audioStarted = true; | ||
} | ||
if (recognized) { | ||
result = (0, _cognitiveServiceEventResultToWebSpeechRecognitionResultList.default)(recognized.result, { | ||
maxAlternatives: _this3.maxAlternatives, | ||
textNormalization: textNormalization | ||
}); | ||
recognizable = !!result[0].transcript; | ||
if (!soundStarted) { | ||
_this3.dispatchEvent(new SpeechRecognitionEvent('soundstart')); | ||
if (recognizable) { | ||
finalizedResults = [].concat((0, _toConsumableArray2.default)(finalizedResults), [result]); | ||
_this3.continuous && _this3.dispatchEvent(new SpeechRecognitionEvent('result', { | ||
results: finalizedResults | ||
})); | ||
} // If it is continuous, we just sent the finalized results. So we don't need to send it again after "audioend" event. | ||
soundStarted = true; | ||
} | ||
if (!speechStarted) { | ||
_this3.dispatchEvent(new SpeechRecognitionEvent('speechstart')); | ||
if (_this3.continuous && recognizable) { | ||
finalEvent = null; | ||
} else { | ||
finalEvent = { | ||
results: finalizedResults, | ||
type: 'result' | ||
}; | ||
} | ||
speechStarted = true; | ||
} | ||
if (!_this3.continuous) { | ||
recognizer.stopContinuousRecognitionAsync(); | ||
} // If event order can be loosened, we can send the recognized event as soon as we receive it. | ||
// 1. If it is not recognizable (no-speech), we should send an "error" event just before "end" event. We will not loosen "error" events. | ||
if (!recognized) { | ||
_context.next = 60; | ||
break; | ||
} | ||
result = (0, _cognitiveServiceEventResultToWebSpeechRecognitionResultList.default)(recognized.result, { | ||
maxAlternatives: _this3.maxAlternatives, | ||
textNormalization: textNormalization | ||
}); | ||
recognizable = !!result[0].transcript; | ||
if (looseEvents && finalEvent && recognizable) { | ||
_this3.dispatchEvent(new SpeechRecognitionEvent(finalEvent.type, finalEvent)); | ||
if (recognizable) { | ||
finalizedResults = [].concat((0, _toConsumableArray2.default)(finalizedResults), [result]); | ||
_this3.continuous && _this3.dispatchEvent(new SpeechRecognitionEvent('result', { | ||
results: finalizedResults | ||
})); | ||
} // If it is continuous, we just sent the finalized results. So we don't need to send it again after "audioend" event. | ||
finalEvent = null; | ||
} | ||
} else if (recognizing) { | ||
_this3.interimResults && _this3.dispatchEvent(new SpeechRecognitionEvent('result', { | ||
results: [].concat((0, _toConsumableArray2.default)(finalizedResults), [(0, _cognitiveServiceEventResultToWebSpeechRecognitionResultList.default)(recognizing.result, { | ||
maxAlternatives: _this3.maxAlternatives, | ||
textNormalization: textNormalization | ||
})]) | ||
})); | ||
} | ||
if (_this3.continuous && recognizable) { | ||
finalEvent = null; | ||
} else { | ||
finalEvent = { | ||
results: finalizedResults, | ||
type: 'result' | ||
}; | ||
} | ||
case 43: | ||
if (_this3.continuous) { | ||
_context.next = 57; | ||
break; | ||
} | ||
_context.next = 57; | ||
return cognitiveServicesAsyncToPromise(recognizer.stopContinuousRecognitionAsync.bind(recognizer))(); | ||
case 57: | ||
// If event order can be loosened, we can send the recognized event as soon as we receive it. | ||
// 1. If it is not recognizable (no-speech), we should send an "error" event just before "end" event. We will not loosen "error" events. | ||
if (looseEvents && finalEvent && recognizable) { | ||
_this3.dispatchEvent(new SpeechRecognitionEvent(finalEvent.type, finalEvent)); | ||
finalEvent = null; | ||
} | ||
_context.next = 61; | ||
break; | ||
case 60: | ||
if (recognizing) { | ||
_this3.interimResults && _this3.dispatchEvent(new SpeechRecognitionEvent('result', { | ||
results: [].concat((0, _toConsumableArray2.default)(finalizedResults), [(0, _cognitiveServiceEventResultToWebSpeechRecognitionResultList.default)(recognizing.result, { | ||
maxAlternatives: _this3.maxAlternatives, | ||
textNormalization: textNormalization | ||
})]) | ||
})); | ||
} | ||
case 61: | ||
case "end": | ||
return _context2.stop(); | ||
return _context.stop(); | ||
} | ||
@@ -688,26 +638,24 @@ } | ||
if (!(!stopping || audioStarted)) { | ||
_context3.next = 33; | ||
_context2.next = 33; | ||
break; | ||
} | ||
return _context3.delegateYield(_loop(loop), "t0", 27); | ||
return _context2.delegateYield(_loop(loop), "t0", 27); | ||
case 27: | ||
_ret = _context3.t0; | ||
_ret = _context2.t0; | ||
if (!(_ret === "break")) { | ||
_context3.next = 30; | ||
_context2.next = 30; | ||
break; | ||
} | ||
return _context3.abrupt("break", 33); | ||
return _context2.abrupt("break", 33); | ||
case 30: | ||
loop++; | ||
_context3.next = 25; | ||
_context2.next = 25; | ||
break; | ||
case 33: | ||
_onAudibleChunk = null; | ||
if (speechStarted) { | ||
@@ -744,10 +692,24 @@ this.dispatchEvent(new SpeechRecognitionEvent('speechend')); | ||
detachAudioConfigEvent(); | ||
_context2.next = 45; | ||
break; | ||
case 41: | ||
_context2.prev = 41; | ||
_context2.t1 = _context2["catch"](4); | ||
// Logging out the erorr because Speech SDK would fail silently. | ||
console.error(_context2.t1); | ||
throw _context2.t1; | ||
case 45: | ||
_context2.prev = 45; | ||
unprepare(); | ||
recognizer.dispose(); | ||
return _context2.finish(45); | ||
case 41: | ||
case 49: | ||
case "end": | ||
return _context3.stop(); | ||
return _context2.stop(); | ||
} | ||
} | ||
}, _callee2, this); | ||
}, _callee, this, [[4, 41, 45, 49]]); | ||
})); | ||
@@ -829,2 +791,73 @@ | ||
}; | ||
} | ||
var _default = function _default(options) { | ||
var _patchOptions = (0, _patchOptions2.default)(options), | ||
_patchOptions$audioCo = _patchOptions.audioConfig, | ||
audioConfig = _patchOptions$audioCo === void 0 ? AudioConfig.fromDefaultMicrophoneInput() : _patchOptions$audioCo, | ||
_patchOptions$enableT = _patchOptions.enableTelemetry, | ||
enableTelemetry = _patchOptions$enableT === void 0 ? true : _patchOptions$enableT, | ||
fetchCredentials = _patchOptions.fetchCredentials, | ||
looseEvents = _patchOptions.looseEvents, | ||
referenceGrammars = _patchOptions.referenceGrammars, | ||
speechRecognitionEndpointId = _patchOptions.speechRecognitionEndpointId, | ||
_patchOptions$textNor = _patchOptions.textNormalization, | ||
textNormalization = _patchOptions$textNor === void 0 ? 'display' : _patchOptions$textNor; | ||
if (!window.navigator.mediaDevices || !window.navigator.mediaDevices.getUserMedia) { | ||
console.warn('web-speech-cognitive-services: This browser does not support WebRTC and it will not work with Cognitive Services Speech Services.'); | ||
return {}; | ||
} | ||
var createRecognizer = | ||
/*#__PURE__*/ | ||
function () { | ||
var _ref11 = (0, _asyncToGenerator2.default)( | ||
/*#__PURE__*/ | ||
_regenerator.default.mark(function _callee2(lang) { | ||
var _ref12, authorizationToken, region, subscriptionKey, speechConfig; | ||
return _regenerator.default.wrap(function _callee2$(_context3) { | ||
while (1) { | ||
switch (_context3.prev = _context3.next) { | ||
case 0: | ||
_context3.next = 2; | ||
return fetchCredentials(); | ||
case 2: | ||
_ref12 = _context3.sent; | ||
authorizationToken = _ref12.authorizationToken; | ||
region = _ref12.region; | ||
subscriptionKey = _ref12.subscriptionKey; | ||
speechConfig = authorizationToken ? SpeechConfig.fromAuthorizationToken(authorizationToken, region) : SpeechConfig.fromSubscription(subscriptionKey, region); | ||
if (speechRecognitionEndpointId) { | ||
speechConfig.endpointId = speechRecognitionEndpointId; | ||
} | ||
speechConfig.outputFormat = OutputFormat.Detailed; | ||
speechConfig.speechRecognitionLanguage = lang || 'en-US'; | ||
return _context3.abrupt("return", new SpeechRecognizer(speechConfig, audioConfig)); | ||
case 11: | ||
case "end": | ||
return _context3.stop(); | ||
} | ||
} | ||
}, _callee2); | ||
})); | ||
return function createRecognizer(_x) { | ||
return _ref11.apply(this, arguments); | ||
}; | ||
}(); | ||
return createSpeechRecognitionPonyfillFromRecognizer({ | ||
audioConfig: audioConfig, | ||
createRecognizer: createRecognizer, | ||
enableTelemetry: enableTelemetry, | ||
looseEvents: looseEvents, | ||
referenceGrammars: referenceGrammars, | ||
textNormalization: textNormalization | ||
}); | ||
}; | ||
@@ -831,0 +864,0 @@ |
@@ -10,6 +10,2 @@ "use strict"; | ||
var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator")); | ||
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator")); | ||
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck")); | ||
@@ -25,6 +21,8 @@ | ||
var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator")); | ||
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator")); | ||
var _eventTargetShim = require("../../external/event-target-shim"); | ||
var _memoizeOne = _interopRequireDefault(require("memoize-one")); | ||
var _onErrorResumeNext = _interopRequireDefault(require("on-error-resume-next")); | ||
@@ -34,3 +32,3 @@ | ||
var _fetchAuthorizationToken = _interopRequireDefault(require("../fetchAuthorizationToken")); | ||
var _createFetchAuthorizationTokenWithCache = _interopRequireDefault(require("../createFetchAuthorizationTokenWithCache")); | ||
@@ -41,2 +39,4 @@ var _fetchCustomVoices = _interopRequireDefault(require("./fetchCustomVoices")); | ||
var _patchOptions2 = _interopRequireDefault(require("../patchOptions")); | ||
var _SpeechSynthesisEvent = _interopRequireDefault(require("./SpeechSynthesisEvent")); | ||
@@ -50,23 +50,19 @@ | ||
var EMPTY_ARRAY = []; | ||
var TOKEN_EXPIRATION = 600000; | ||
var TOKEN_EARLY_RENEWAL = 60000; | ||
var _default = function _default(_ref) { | ||
var audioContext = _ref.audioContext, | ||
authorizationToken = _ref.authorizationToken, | ||
_ref$ponyfill = _ref.ponyfill, | ||
ponyfill = _ref$ponyfill === void 0 ? { | ||
var _default = function _default(options) { | ||
var _patchOptions = (0, _patchOptions2.default)(options), | ||
audioContext = _patchOptions.audioContext, | ||
fetchCredentials = _patchOptions.fetchCredentials, | ||
_patchOptions$ponyfil = _patchOptions.ponyfill, | ||
ponyfill = _patchOptions$ponyfil === void 0 ? { | ||
AudioContext: window.AudioContext || window.webkitAudioContext | ||
} : _ref$ponyfill, | ||
_ref$region = _ref.region, | ||
region = _ref$region === void 0 ? 'westus' : _ref$region, | ||
speechSynthesisDeploymentId = _ref.speechSynthesisDeploymentId, | ||
_ref$speechSynthesisO = _ref.speechSynthesisOutputFormat, | ||
speechSynthesisOutputFormat = _ref$speechSynthesisO === void 0 ? DEFAULT_OUTPUT_FORMAT : _ref$speechSynthesisO, | ||
subscriptionKey = _ref.subscriptionKey; | ||
} : _patchOptions$ponyfil, | ||
_patchOptions$region = _patchOptions.region, | ||
region = _patchOptions$region === void 0 ? 'westus' : _patchOptions$region, | ||
speechSynthesisDeploymentId = _patchOptions.speechSynthesisDeploymentId, | ||
_patchOptions$speechS = _patchOptions.speechSynthesisOutputFormat, | ||
speechSynthesisOutputFormat = _patchOptions$speechS === void 0 ? DEFAULT_OUTPUT_FORMAT : _patchOptions$speechS, | ||
subscriptionKey = _patchOptions.subscriptionKey; | ||
if (!authorizationToken && !subscriptionKey) { | ||
console.warn('web-speech-cognitive-services: Either authorization token or subscription key must be specified'); | ||
return {}; | ||
} else if (!ponyfill.AudioContext) { | ||
if (!ponyfill.AudioContext) { | ||
console.warn('web-speech-cognitive-services: This browser does not support Web Audio and it will not work with Cognitive Services Speech Services.'); | ||
@@ -76,21 +72,63 @@ return {}; | ||
var fetchMemoizedAuthorizationToken = (0, _memoizeOne.default)(function (_ref2) { | ||
var region = _ref2.region, | ||
subscriptionKey = _ref2.subscriptionKey; | ||
return (0, _fetchAuthorizationToken.default)({ | ||
region: region, | ||
subscriptionKey: subscriptionKey | ||
}); | ||
}, function (arg, prevArg) { | ||
return arg.region === prevArg.region && arg.subscriptionKey === prevArg.subscriptionKey && arg.now - prevArg.now < TOKEN_EXPIRATION - TOKEN_EARLY_RENEWAL; | ||
}); | ||
var fetchAuthorizationTokenWithCache = (0, _createFetchAuthorizationTokenWithCache.default)(); | ||
var getAuthorizationToken = function getAuthorizationToken() { | ||
return typeof authorizationToken === 'function' ? authorizationToken() : authorizationToken ? authorizationToken : fetchMemoizedAuthorizationToken({ | ||
now: Date.now, | ||
region: region, | ||
subscriptionKey: subscriptionKey | ||
}); | ||
}; | ||
var fetchAuthorizationTokenCredentials = | ||
/*#__PURE__*/ | ||
function () { | ||
var _ref = (0, _asyncToGenerator2.default)( | ||
/*#__PURE__*/ | ||
_regenerator.default.mark(function _callee() { | ||
var _ref2, authorizationToken, region, subscriptionKey; | ||
return _regenerator.default.wrap(function _callee$(_context) { | ||
while (1) { | ||
switch (_context.prev = _context.next) { | ||
case 0: | ||
_context.next = 2; | ||
return fetchCredentials(); | ||
case 2: | ||
_ref2 = _context.sent; | ||
authorizationToken = _ref2.authorizationToken; | ||
region = _ref2.region; | ||
subscriptionKey = _ref2.subscriptionKey; | ||
if (!authorizationToken) { | ||
_context.next = 8; | ||
break; | ||
} | ||
return _context.abrupt("return", { | ||
authorizationToken: authorizationToken, | ||
region: region | ||
}); | ||
case 8: | ||
_context.next = 10; | ||
return fetchAuthorizationTokenWithCache({ | ||
region: region, | ||
subscriptionKey: subscriptionKey | ||
}); | ||
case 10: | ||
_context.t0 = _context.sent; | ||
_context.t1 = region; | ||
return _context.abrupt("return", { | ||
authorizationToken: _context.t0, | ||
region: _context.t1 | ||
}); | ||
case 13: | ||
case "end": | ||
return _context.stop(); | ||
} | ||
} | ||
}, _callee); | ||
})); | ||
return function fetchAuthorizationTokenCredentials() { | ||
return _ref.apply(this, arguments); | ||
}; | ||
}(); | ||
var SpeechSynthesis = | ||
@@ -150,5 +188,4 @@ /*#__PURE__*/ | ||
deploymentId: speechSynthesisDeploymentId, | ||
getAuthorizationToken: getAuthorizationToken, | ||
outputFormat: speechSynthesisOutputFormat, | ||
region: region | ||
fetchAuthorizationTokenCredentials: fetchAuthorizationTokenCredentials, | ||
outputFormat: speechSynthesisOutputFormat | ||
}); | ||
@@ -164,11 +201,11 @@ | ||
/*#__PURE__*/ | ||
_regenerator.default.mark(function _callee3() { | ||
_regenerator.default.mark(function _callee4() { | ||
var _this3 = this; | ||
return _regenerator.default.wrap(function _callee3$(_context3) { | ||
return _regenerator.default.wrap(function _callee4$(_context4) { | ||
while (1) { | ||
switch (_context3.prev = _context3.next) { | ||
switch (_context4.prev = _context4.next) { | ||
case 0: | ||
if (!speechSynthesisDeploymentId) { | ||
_context3.next = 7; | ||
_context4.next = 7; | ||
break; | ||
@@ -178,3 +215,3 @@ } | ||
if (!subscriptionKey) { | ||
_context3.next = 5; | ||
_context4.next = 5; | ||
break; | ||
@@ -184,3 +221,3 @@ } | ||
console.warn('web-speech-cognitive-services: Listing of custom voice models are only available when using subscription key.'); | ||
_context3.next = 5; | ||
_context4.next = 5; | ||
return (0, _onErrorResumeNext.default)( | ||
@@ -190,9 +227,9 @@ /*#__PURE__*/ | ||
/*#__PURE__*/ | ||
_regenerator.default.mark(function _callee() { | ||
_regenerator.default.mark(function _callee2() { | ||
var voices; | ||
return _regenerator.default.wrap(function _callee$(_context) { | ||
return _regenerator.default.wrap(function _callee2$(_context2) { | ||
while (1) { | ||
switch (_context.prev = _context.next) { | ||
switch (_context2.prev = _context2.next) { | ||
case 0: | ||
_context.next = 2; | ||
_context2.next = 2; | ||
return (0, _fetchCustomVoices.default)({ | ||
@@ -205,3 +242,3 @@ deploymentId: speechSynthesisDeploymentId, | ||
case 2: | ||
voices = _context.sent; | ||
voices = _context2.sent; | ||
@@ -214,14 +251,14 @@ _this3.getVoices = function () { | ||
case "end": | ||
return _context.stop(); | ||
return _context2.stop(); | ||
} | ||
} | ||
}, _callee); | ||
}, _callee2); | ||
}))); | ||
case 5: | ||
_context3.next = 9; | ||
_context4.next = 9; | ||
break; | ||
case 7: | ||
_context3.next = 9; | ||
_context4.next = 9; | ||
return (0, _onErrorResumeNext.default)( | ||
@@ -231,26 +268,24 @@ /*#__PURE__*/ | ||
/*#__PURE__*/ | ||
_regenerator.default.mark(function _callee2() { | ||
var voices; | ||
return _regenerator.default.wrap(function _callee2$(_context2) { | ||
_regenerator.default.mark(function _callee3() { | ||
var _ref5, authorizationToken, region, voices; | ||
return _regenerator.default.wrap(function _callee3$(_context3) { | ||
while (1) { | ||
switch (_context2.prev = _context2.next) { | ||
switch (_context3.prev = _context3.next) { | ||
case 0: | ||
_context2.t0 = _fetchVoices.default; | ||
_context2.next = 3; | ||
return getAuthorizationToken(); | ||
_context3.next = 2; | ||
return fetchAuthorizationTokenCredentials(); | ||
case 3: | ||
_context2.t1 = _context2.sent; | ||
_context2.t2 = speechSynthesisDeploymentId; | ||
_context2.t3 = region; | ||
_context2.t4 = { | ||
authorizationToken: _context2.t1, | ||
deploymentId: _context2.t2, | ||
region: _context2.t3 | ||
}; | ||
_context2.next = 9; | ||
return (0, _context2.t0)(_context2.t4); | ||
case 2: | ||
_ref5 = _context3.sent; | ||
authorizationToken = _ref5.authorizationToken; | ||
region = _ref5.region; | ||
_context3.next = 7; | ||
return (0, _fetchVoices.default)({ | ||
authorizationToken: authorizationToken, | ||
region: region | ||
}); | ||
case 9: | ||
voices = _context2.sent; | ||
case 7: | ||
voices = _context3.sent; | ||
@@ -261,8 +296,8 @@ _this3.getVoices = function () { | ||
case 11: | ||
case 9: | ||
case "end": | ||
return _context2.stop(); | ||
return _context3.stop(); | ||
} | ||
} | ||
}, _callee2); | ||
}, _callee3); | ||
}))); | ||
@@ -275,6 +310,6 @@ | ||
case "end": | ||
return _context3.stop(); | ||
return _context4.stop(); | ||
} | ||
} | ||
}, _callee3, this); | ||
}, _callee4, this); | ||
})); | ||
@@ -281,0 +316,0 @@ |
@@ -34,3 +34,3 @@ "use strict"; | ||
_regenerator.default.mark(function _callee(_ref) { | ||
var deploymentId, getAuthorizationToken, _ref$lang, lang, outputFormat, pitch, rate, region, text, _ref$voice, voice, volume, authorizationToken, ssml, url, res; | ||
var deploymentId, fetchAuthorizationTokenCredentials, _ref$lang, lang, outputFormat, pitch, rate, text, _ref$voice, voice, volume, _ref3, authorizationToken, region, ssml, url, res; | ||
@@ -41,3 +41,3 @@ return _regenerator.default.wrap(function _callee$(_context) { | ||
case 0: | ||
deploymentId = _ref.deploymentId, getAuthorizationToken = _ref.getAuthorizationToken, _ref$lang = _ref.lang, lang = _ref$lang === void 0 ? DEFAULT_LANGUAGE : _ref$lang, outputFormat = _ref.outputFormat, pitch = _ref.pitch, rate = _ref.rate, region = _ref.region, text = _ref.text, _ref$voice = _ref.voice, voice = _ref$voice === void 0 ? DEFAULT_VOICE : _ref$voice, volume = _ref.volume; | ||
deploymentId = _ref.deploymentId, fetchAuthorizationTokenCredentials = _ref.fetchAuthorizationTokenCredentials, _ref$lang = _ref.lang, lang = _ref$lang === void 0 ? DEFAULT_LANGUAGE : _ref$lang, outputFormat = _ref.outputFormat, pitch = _ref.pitch, rate = _ref.rate, text = _ref.text, _ref$voice = _ref.voice, voice = _ref$voice === void 0 ? DEFAULT_VOICE : _ref$voice, volume = _ref.volume; | ||
@@ -53,6 +53,8 @@ if (text) { | ||
_context.next = 5; | ||
return getAuthorizationToken(); | ||
return fetchAuthorizationTokenCredentials(); | ||
case 5: | ||
authorizationToken = _context.sent; | ||
_ref3 = _context.sent; | ||
authorizationToken = _ref3.authorizationToken; | ||
region = _ref3.region; | ||
ssml = (0, _isSSML.default)(text) ? text : (0, _buildSSML.default)({ | ||
@@ -68,3 +70,3 @@ lang: lang, | ||
url = deploymentId ? SYNTHESIS_CUSTOM_VOICE_URL_TEMPLATE.replace(/\{region\}/, encodeURI(region)).replace(/\{deploymentId\}/, encodeURI(deploymentId)) : SYNTHESIS_URL_TEMPLATE.replace(/\{region\}/, encodeURI(region)); | ||
_context.next = 10; | ||
_context.next = 12; | ||
return fetch(url, { | ||
@@ -80,7 +82,7 @@ headers: { | ||
case 10: | ||
case 12: | ||
res = _context.sent; | ||
if (res.ok) { | ||
_context.next = 13; | ||
_context.next = 15; | ||
break; | ||
@@ -91,6 +93,6 @@ } | ||
case 13: | ||
case 15: | ||
return _context.abrupt("return", res.arrayBuffer()); | ||
case 14: | ||
case 16: | ||
case "end": | ||
@@ -97,0 +99,0 @@ return _context.stop(); |
@@ -8,3 +8,3 @@ "use strict"; | ||
}); | ||
exports.default = _default; | ||
exports.default = fetchVoices; | ||
@@ -18,8 +18,8 @@ var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator")); | ||
/* eslint no-magic-numbers: ["error", { "ignore": [0, 1, -1] }] */ | ||
function _default(_x) { | ||
return _ref2.apply(this, arguments); | ||
function fetchVoices(_x) { | ||
return _fetchVoices.apply(this, arguments); | ||
} | ||
function _ref2() { | ||
_ref2 = (0, _asyncToGenerator2.default)( | ||
function _fetchVoices() { | ||
_fetchVoices = (0, _asyncToGenerator2.default)( | ||
/*#__PURE__*/ | ||
@@ -57,6 +57,6 @@ _regenerator.default.mark(function _callee(_ref) { | ||
voices = _context.sent; | ||
return _context.abrupt("return", voices.map(function (_ref3) { | ||
var gender = _ref3.Gender, | ||
lang = _ref3.Locale, | ||
voiceURI = _ref3.Name; | ||
return _context.abrupt("return", voices.map(function (_ref2) { | ||
var gender = _ref2.Gender, | ||
lang = _ref2.Locale, | ||
voiceURI = _ref2.Name; | ||
return new _SpeechSynthesisVoice.default({ | ||
@@ -67,5 +67,5 @@ gender: gender, | ||
}); | ||
}).sort(function (_ref4, _ref5) { | ||
var x = _ref4.name; | ||
var y = _ref5.name; | ||
}).sort(function (_ref3, _ref4) { | ||
var x = _ref3.name; | ||
var y = _ref4.name; | ||
return x > y ? 1 : x < y ? -1 : 0; | ||
@@ -81,4 +81,4 @@ })); | ||
})); | ||
return _ref2.apply(this, arguments); | ||
return _fetchVoices.apply(this, arguments); | ||
} | ||
//# sourceMappingURL=fetchVoices.js.map |
@@ -99,3 +99,3 @@ "use strict"; | ||
_regenerator.default.mark(function _callee(_ref2) { | ||
var deploymentId, getAuthorizationToken, outputFormat, region; | ||
var deploymentId, fetchAuthorizationTokenCredentials, outputFormat; | ||
return _regenerator.default.wrap(function _callee$(_context) { | ||
@@ -105,6 +105,6 @@ while (1) { | ||
case 0: | ||
deploymentId = _ref2.deploymentId, getAuthorizationToken = _ref2.getAuthorizationToken, outputFormat = _ref2.outputFormat, region = _ref2.region; | ||
deploymentId = _ref2.deploymentId, fetchAuthorizationTokenCredentials = _ref2.fetchAuthorizationTokenCredentials, outputFormat = _ref2.outputFormat; | ||
this.arrayBufferPromise = (0, _fetchSpeechData.default)({ | ||
deploymentId: deploymentId, | ||
getAuthorizationToken: getAuthorizationToken, | ||
fetchAuthorizationTokenCredentials: fetchAuthorizationTokenCredentials, | ||
lang: this.lang || window.navigator.language, | ||
@@ -114,3 +114,2 @@ outputFormat: outputFormat, | ||
rate: this.rate, | ||
region: region, | ||
text: this.text, | ||
@@ -117,0 +116,0 @@ voice: this.voice && this.voice.voiceURI, |
{ | ||
"name": "web-speech-cognitive-services", | ||
"version": "5.0.2-master.e668a0d", | ||
"version": "5.0.2-master.e85a10c", | ||
"description": "Polyfill Web Speech API with Cognitive Services Speech-to-Text service", | ||
@@ -61,11 +61,10 @@ "keywords": [ | ||
"@babel/preset-env": "^7.5.5", | ||
"@babel/preset-react": "^7.0.0", | ||
"babel-core": "7.0.0-bridge.0", | ||
"babel-jest": "^24.8.0", | ||
"babel-jest": "^24.9.0", | ||
"babel-plugin-transform-inline-environment-variables": "^0.4.3", | ||
"eslint": "^6.1.0", | ||
"jest": "^24.8.0", | ||
"eslint": "^6.6.0", | ||
"jest": "^24.9.0", | ||
"lolex": "^5.1.1", | ||
"microsoft-speech-browser-sdk": "^0.0.12", | ||
"prettier": "^1.19.1", | ||
"rimraf": "^2.6.3" | ||
"rimraf": "^3.0.0" | ||
}, | ||
@@ -72,0 +71,0 @@ "dependencies": { |
146
README.md
@@ -53,4 +53,6 @@ # web-speech-cognitive-services | ||
const { speechSynthesis, SpeechSynthesisUtterance } = window.WebSpeechCognitiveServices.create({ | ||
region: 'westus', | ||
subscriptionKey: 'YOUR_SUBSCRIPTION_KEY' | ||
credentials: { | ||
region: 'westus', | ||
subscriptionKey: 'YOUR_SUBSCRIPTION_KEY' | ||
} | ||
}); | ||
@@ -120,12 +122,22 @@ | ||
<td> | ||
<code>authorizationToken: (</code><br /> | ||
<code> string ||</code><br /> | ||
<code> Promise<string> ||</code><br /> | ||
<code> () => string ||</code><br /> | ||
<code> () => Promise<string></code><br /> | ||
<code>)</code> | ||
<code>credentials: (</code><br /> | ||
<code> Credentials ||</code><br /> | ||
<code> Promise<Credentials> ||</code><br /> | ||
<code> () => Credentials ||</code><br /> | ||
<code> () => Promise<Credentials></code><br /> | ||
<code>)</code><br /> | ||
<br /> | ||
<code>ICredentials: {</code><br /> | ||
<code> authorizationToken: string,</code><br /> | ||
<code> region: string</code><br /> | ||
<code>} || {</code><br /> | ||
<code> region: string,</code><br /> | ||
<code> subscriptionKey: string</code><br /> | ||
<code>}</code> | ||
</td> | ||
<td>(Requires either<br /><code>authorizationToken</code> or<br /><code>subscriptionKey</code>)</td> | ||
<td>(Required)</td> | ||
<td> | ||
Authorization token from Cognitive Services. Please refer to <a href="https://docs.microsoft.com/en-us/azure/cognitive-services/authentication">this article</a> to obtain an authorization token. | ||
Credentials (including Azure region) from Cognitive Services. Please refer to <a href="https://docs.microsoft.com/en-us/azure/cognitive-services/authentication">this article</a> to obtain an authorization token.<br /> | ||
<br /> | ||
Subscription key is not recommended for production use as it will be leaked in the browser. | ||
</td> | ||
@@ -165,9 +177,2 @@ </tr> | ||
<tr> | ||
<td><code>region: string</code></td> | ||
<td><code>"westus"</code></td> | ||
<td> | ||
Azure region of Cognitive Services to use. | ||
</td> | ||
</tr> | ||
<tr> | ||
<td><code>speechRecognitionEndpointId: string</code></td> | ||
@@ -192,9 +197,2 @@ <td><code>undefined</code></td> | ||
<tr> | ||
<td><code>subscriptionKey: string</code></td> | ||
<td>(Requires either<br /><code>authorizationToken</code> or<br /><code>subscriptionKey</code>)</td> | ||
<td> | ||
Subscription key to use. This is not recommended for production use as the subscription key will be leaked in the browser. | ||
</td> | ||
</tr> | ||
<tr> | ||
<td><code>textNormalization: string</code></td> | ||
@@ -227,4 +225,6 @@ <td><code>"display"</code></td> | ||
} = await createSpeechRecognitionPonyfill({ | ||
region: 'westus', | ||
subscriptionKey: 'YOUR_SUBSCRIPTION_KEY' | ||
credentials: { | ||
region: 'westus', | ||
subscriptionKey: 'YOUR_SUBSCRIPTION_KEY' | ||
} | ||
}); | ||
@@ -258,4 +258,6 @@ | ||
} = await createPonyfill({ | ||
region: 'westus', | ||
subscriptionKey: 'YOUR_SUBSCRIPTION_KEY' | ||
credentials: { | ||
region: 'westus', | ||
subscriptionKey: 'YOUR_SUBSCRIPTION_KEY' | ||
} | ||
}); | ||
@@ -282,4 +284,6 @@ | ||
} = await createSpeechSynthesisPonyfill({ | ||
region: 'westus', | ||
subscriptionKey: 'YOUR_SUBSCRIPTION_KEY' | ||
credentials: { | ||
region: 'westus', | ||
subscriptionKey: 'YOUR_SUBSCRIPTION_KEY' | ||
} | ||
}); | ||
@@ -309,36 +313,26 @@ | ||
import createPonyfill from 'web-speech-cognitive-services/lib/SpeechServices'; | ||
import React from 'react'; | ||
import React, { useEffect, useState } from 'react'; | ||
import Say from 'react-say'; | ||
export default class extends React.Component { | ||
constructor(props) { | ||
super(props); | ||
export default () => { | ||
const [ponyfill, setPonyfill] = useState(); | ||
this.state = {}; | ||
} | ||
useEffect(async () => { | ||
setPonyfill(await createPonyfill({ | ||
credentials: { | ||
region: 'westus', | ||
subscriptionKey: 'YOUR_SUBSCRIPTION_KEY' | ||
} | ||
})); | ||
}, [setPonyfill]); | ||
async componentDidMount() { | ||
const ponyfill = await createPonyfill({ | ||
region: 'westus', | ||
subscriptionKey: 'YOUR_SUBSCRIPTION_KEY' | ||
}); | ||
this.setState(() => ({ ponyfill })); | ||
} | ||
render() { | ||
const { | ||
state: { ponyfill } | ||
} = this; | ||
return ( | ||
ponyfill && | ||
<Say | ||
speechSynthesis={ ponyfill.speechSynthesis } | ||
speechSynthesisUtterance={ ponyfill.SpeechSynthesisUtterance } | ||
text="Hello, World!" | ||
/> | ||
); | ||
} | ||
} | ||
return ( | ||
ponyfill && | ||
<Say | ||
speechSynthesis={ ponyfill.speechSynthesis } | ||
speechSynthesisUtterance={ ponyfill.SpeechSynthesisUtterance } | ||
text="Hello, World!" | ||
/> | ||
); | ||
}; | ||
``` | ||
@@ -354,8 +348,10 @@ | ||
const ponyfill = await createPonyfill({ | ||
authorizationToken: 'YOUR_AUTHORIZATION_TOKEN', | ||
region: 'westus', | ||
credentials: { | ||
authorizationToken: 'YOUR_AUTHORIZATION_TOKEN', | ||
region: 'westus' | ||
} | ||
}); | ||
``` | ||
You can also provide an async function that will fetch the authorization token on-demand. You should cache the authorization token for subsequent request. For simplicity of this code snippets, we are not caching the result. | ||
You can also provide an async function that will fetch the authorization token and Azure region on-demand. You should cache the authorization token for subsequent request. For simplicity of this code snippets, we are not caching the result. | ||
@@ -366,4 +362,6 @@ ```jsx | ||
const ponyfill = await createPonyfill({ | ||
authorizationToken: () => fetch('https://example.com/your-token').then(res => res.text()), | ||
region: 'westus', | ||
credentials: () => fetch('https://example.com/your-token').then(res => ({ | ||
authorizationToken: res.text(), | ||
region: 'westus' | ||
})) | ||
}); | ||
@@ -395,4 +393,6 @@ ``` | ||
} = await createPonyfill({ | ||
region: 'westus', | ||
subscriptionKey: 'YOUR_SUBSCRIPTION_KEY' | ||
credentials: { | ||
region: 'westus', | ||
subscriptionKey: 'YOUR_SUBSCRIPTION_KEY' | ||
} | ||
}); | ||
@@ -422,5 +422,7 @@ | ||
const ponyfill = await createPonyfill({ | ||
region: 'westus', | ||
credentials: { | ||
region: 'westus', | ||
subscriptionKey: 'YOUR_SUBSCRIPTION_KEY' | ||
}, | ||
speechRecognitionEndpointId: '12345678-1234-5678-abcd-12345678abcd', | ||
subscriptionKey: 'YOUR_SUBSCRIPTION_KEY' | ||
}); | ||
@@ -439,5 +441,7 @@ ``` | ||
const ponyfill = await createPonyfill({ | ||
region: 'westus', | ||
credentials: { | ||
region: 'westus', | ||
subscriptionKey: 'YOUR_SUBSCRIPTION_KEY' | ||
}, | ||
speechSynthesisDeploymentId: '12345678-1234-5678-abcd-12345678abcd', | ||
subscriptionKey: 'YOUR_SUBSCRIPTION_KEY' | ||
}); | ||
@@ -444,0 +448,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
4418747
13
101
9454
520