web-speech-cognitive-services
Advanced tools
Comparing version 4.0.1-master.fcd6f40 to 5.0.0-master.edfd25f
@@ -23,3 +23,3 @@ # Changelog | ||
- Speech synthesis: Fix [#32](https://github.com/compulim/web-speech-cognitive-services/issues/32), fetch voices from services, in PR [#35](https://github.com/compulim/web-speech-cognitive-services/pull/35) | ||
- Speech synthesis: Fix [#34](https://github.com/compulim/web-speech-cognitive-services/issues/34), in PR [#36](https://github.com/compulim/web-speech-cognitive-services/pull/36) and PR [#XXX](https://github.com/compulim/web-speech-cognitive-services/pull/XXX) | ||
- Speech synthesis: Fix [#34](https://github.com/compulim/web-speech-cognitive-services/issues/34), in PR [#36](https://github.com/compulim/web-speech-cognitive-services/pull/36) and PR [#44](https://github.com/compulim/web-speech-cognitive-services/pull/44) | ||
- Support user-controlled `AudioContext` object to be passed as an option named `audioContext` | ||
@@ -34,5 +34,12 @@ - If no `audioContext` option is passed, will create a new `AudioContext` object on first synthesis | ||
- Use option `speechRecognitionEndpointId` | ||
- Speech synthesis: Fix [#28](https://github.com/compulim/web-speech-cognitive-services/issues/28), support custom voice font, in PR [#41](https://github.com/compulim/web-speech-cognitive-services/pull/41) | ||
- Speech synthesis: Fix [#28](https://github.com/compulim/web-speech-cognitive-services/issues/28) and [#62](https://github.com/compulim/web-speech-cognitive-services/issues/62), support custom voice font, in PR [#41](https://github.com/compulim/web-speech-cognitive-services/pull/41) and PR [#67](https://github.com/compulim/web-speech-cognitive-services/pull/67) | ||
- Use option `speechSynthesisDeploymentId` | ||
- Voice list is only fetch when using subscription key | ||
- Speech synthesis: Fix [#48](https://github.com/compulim/web-speech-cognitive-services/issues/48), support output format through `outputFormat` option, in PR [#49](https://github.com/compulim/web-speech-cognitive-services/pull/49) | ||
- `*`: Fix [#47](https://github.com/compulim/web-speech-cognitive-services/issues/47), add `enableTelemetry` option for disabling collecting telemetry data in Speech SDK, in PR [#51](https://github.com/compulim/web-speech-cognitive-services/pull/51) and PR [#66](https://github.com/compulim/web-speech/cognitive-services/pull/66) | ||
- `*`: Fix [#53](https://github.com/compulim/web-speech-cognitive-services/issues/53), added ESLint, in PR [#54](https://github.com/compulim/web-speech-cognitive-services/pull/54) | ||
- Speech synthesis: Fix [#39](https://github.com/compulim/web-speech-cognitive-services/issues/39), support SSML utterance, in PR [#57](https://github.com/compulim/web-speech-cognitive-services/pull/57) | ||
- Speech recognition: Fix [#59](https://github.com/compulim/web-speech-cognitive-services/issues/59), support `stop()` function by finalizing partial speech, in PR [#60](https://github.com/compulim/web-speech-cognitive-services/pull/60) | ||
- Fix [#67](https://github.com/compulim/web-speech-cognitive-services/issues/67), add warning when using subscription key instead of authorization token, in PR [#69](https://github.com/compulim/web-speech-cognitive-services/pull/69) | ||
- Fix [#70](https://github.com/compulim/web-speech-cognitive-services/issues/70), fetch authorization token before every synthesis, in PR [#71](https://github.com/compulim/web-speech-cognitive-services/pull/71) | ||
@@ -57,2 +64,5 @@ ### Changed | ||
- Bumped to [microsoft-cognitiveservices-speech-sdk@1.6.0](https://www.npmjs.com/package/microsoft-cognitiveservices-speech-sdk), in PR [#22](https://github.com/compulim/web-speech-cognitive-services/pull/22) | ||
- Fix [#55](https://github.com/compulim/web-speech-cognitive-services/issues/55) and [#63](https://github.com/compulim/web-speech-cognitive-services/issues/63). Moves to [WHATWG `EventTarget` interface](https://dom.spec.whatwg.org/#interface-eventtarget), in PR [#56](https://github.com/compulim/web-speech-cognitive-services/pulls/56) and PR [#64](https://github.com/compulim/web-speech-cognitive-services/pulls/64) | ||
- Instead of including `event-target-shim@5.0.1`, we are adopting its source code, in PR [#72](https://github.com/compulim/web-speech-cognitive-services/pulls/72) | ||
- This is because the original package requires browser to support rest/spread operators | ||
@@ -59,0 +69,0 @@ ### Fixed |
@@ -46,3 +46,3 @@ "use strict"; | ||
var VERSION = "4.0.1-master.fcd6f40"; | ||
var VERSION = "5.0.0-master.edfd25f"; | ||
@@ -49,0 +49,0 @@ function buildSpeechResult(transcript, confidence, isFinal) { |
@@ -40,5 +40,18 @@ "use strict"; | ||
var shouldWarnOnSubscriptionKey = true; | ||
function createSpeechServicesPonyfill() { | ||
var ponyfill = _objectSpread({}, _SpeechToText.default.apply(void 0, arguments), {}, _TextToSpeech.default.apply(void 0, arguments)); | ||
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++) { | ||
args[_key - 1] = arguments[_key]; | ||
} | ||
var ponyfill = _objectSpread({}, _SpeechToText.default.apply(void 0, [options].concat(args)), {}, _TextToSpeech.default.apply(void 0, [options].concat(args))); | ||
return _objectSpread({}, ponyfill, { | ||
@@ -52,7 +65,6 @@ then: function then(resolve) { | ||
; | ||
var meta = document.createElement('meta'); | ||
meta.setAttribute('name', 'web-speech-cognitive-services'); | ||
meta.setAttribute('content', "version=".concat("4.0.1-master.fcd6f40")); | ||
meta.setAttribute('content', "version=".concat("5.0.0-master.edfd25f")); | ||
document.head.appendChild(meta); | ||
//# sourceMappingURL=SpeechServices.js.map |
@@ -41,3 +41,3 @@ "use strict"; | ||
if (!(res.status !== 200)) { | ||
if (res.ok) { | ||
_context.next = 6; | ||
@@ -44,0 +44,0 @@ break; |
"use strict"; | ||
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard"); | ||
Object.defineProperty(exports, "__esModule", { | ||
@@ -10,6 +8,13 @@ value: true | ||
var CognitiveServicesSpeechSDK = _interopRequireWildcard(require("microsoft-cognitiveservices-speech-sdk/distrib/lib/microsoft.cognitiveservices.speech.sdk")); | ||
var _microsoftCognitiveservicesSpeech = require("microsoft-cognitiveservices-speech-sdk/distrib/lib/microsoft.cognitiveservices.speech.sdk"); | ||
var _default = CognitiveServicesSpeechSDK; | ||
// We are only importing what we need. | ||
var _default = { | ||
AudioConfig: _microsoftCognitiveservicesSpeech.AudioConfig, | ||
OutputFormat: _microsoftCognitiveservicesSpeech.OutputFormat, | ||
ResultReason: _microsoftCognitiveservicesSpeech.ResultReason, | ||
SpeechConfig: _microsoftCognitiveservicesSpeech.SpeechConfig, | ||
SpeechRecognizer: _microsoftCognitiveservicesSpeech.SpeechRecognizer | ||
}; | ||
exports.default = _default; | ||
//# sourceMappingURL=SpeechSDK.js.map |
@@ -45,6 +45,6 @@ "use strict"; | ||
return resultList; | ||
} else { | ||
return []; | ||
} | ||
return []; | ||
} | ||
//# sourceMappingURL=cognitiveServiceEventResultToWebSpeechRecognitionResultList.js.map |
@@ -12,4 +12,2 @@ "use strict"; | ||
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); | ||
var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator")); | ||
@@ -19,4 +17,2 @@ | ||
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck")); | ||
var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass")); | ||
@@ -30,2 +26,8 @@ | ||
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); | ||
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck")); | ||
var _eventTargetShim = require("../../external/event-target-shim"); | ||
var _cognitiveServiceEventResultToWebSpeechRecognitionResultList = _interopRequireDefault(require("./cognitiveServiceEventResultToWebSpeechRecognitionResultList")); | ||
@@ -35,4 +37,2 @@ | ||
var _DOMEventEmitter2 = _interopRequireDefault(require("../../Util/DOMEventEmitter")); | ||
var _SpeechGrammarList = _interopRequireDefault(require("./SpeechGrammarList")); | ||
@@ -120,27 +120,78 @@ | ||
var SpeechRecognitionEvent = function SpeechRecognitionEvent(type) { | ||
var _ref2 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}, | ||
data = _ref2.data, | ||
emma = _ref2.emma, | ||
interpretation = _ref2.interpretation, | ||
resultIndex = _ref2.resultIndex, | ||
results = _ref2.results; | ||
(0, _classCallCheck2.default)(this, SpeechRecognitionEvent); | ||
this.data = data; | ||
this.emma = emma; | ||
this.interpretation = interpretation; | ||
this.resultIndex = resultIndex; | ||
this.results = results; | ||
this.type = type; | ||
}; | ||
var _default = function _default() { | ||
var _ref2 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, | ||
_ref2$audioConfig = _ref2.audioConfig, | ||
audioConfig = _ref2$audioConfig === void 0 ? AudioConfig.fromDefaultMicrophoneInput() : _ref2$audioConfig, | ||
authorizationToken = _ref2.authorizationToken, | ||
referenceGrammars = _ref2.referenceGrammars, | ||
_ref2$region = _ref2.region, | ||
region = _ref2$region === void 0 ? 'westus' : _ref2$region, | ||
speechRecognitionEndpointId = _ref2.speechRecognitionEndpointId, | ||
subscriptionKey = _ref2.subscriptionKey, | ||
_ref2$textNormalizati = _ref2.textNormalization, | ||
textNormalization = _ref2$textNormalizati === void 0 ? 'display' : _ref2$textNormalizati; | ||
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, | ||
referenceGrammars = _ref3.referenceGrammars, | ||
_ref3$region = _ref3.region, | ||
region = _ref3$region === void 0 ? 'westus' : _ref3$region, | ||
speechRecognitionEndpointId = _ref3.speechRecognitionEndpointId, | ||
subscriptionKey = _ref3.subscriptionKey, | ||
_ref3$textNormalizati = _ref3.textNormalization, | ||
textNormalization = _ref3$textNormalizati === void 0 ? 'display' : _ref3$textNormalizati; | ||
if (!authorizationToken && !subscriptionKey) { | ||
console.warn('Either authorizationToken or subscriptionKey must be specified'); | ||
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('This browser does not support WebRTC and it will not work with Cognitive Services Speech Services.'); | ||
console.warn('web-speech-cognitive-services: This browser does not support WebRTC and it will not work with Cognitive Services Speech Services.'); | ||
return {}; | ||
} | ||
var _onAudibleChunk; | ||
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) { | ||
return _objectSpread({}, reader, { | ||
read: improviseAsync(reader.read.bind(reader), function (chunk) { | ||
// The magic number 150 is measured by: | ||
// 1. Set microphone volume to 0 | ||
// 2. Observe the amplitude (100-110) for the first few chunks | ||
// (This is 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 (muted) { | ||
return { | ||
buffer: new ArrayBuffer(0), | ||
isEnd: true, | ||
timeReceived: Date.now() | ||
}; | ||
} | ||
return chunk; | ||
}) | ||
}); | ||
}); // If enableTelemetry is set to null or non-boolean, we will default to true. | ||
SpeechRecognizer.enableTelemetry(enableTelemetry !== false); | ||
var SpeechRecognition = | ||
/*#__PURE__*/ | ||
function (_DOMEventEmitter) { | ||
(0, _inherits2.default)(SpeechRecognition, _DOMEventEmitter); | ||
function (_EventTarget) { | ||
(0, _inherits2.default)(SpeechRecognition, _EventTarget); | ||
@@ -151,3 +202,3 @@ function SpeechRecognition() { | ||
(0, _classCallCheck2.default)(this, SpeechRecognition); | ||
_this = (0, _possibleConstructorReturn2.default)(this, (0, _getPrototypeOf2.default)(SpeechRecognition).call(this, ['audiostart', 'soundstart', 'speechstart', 'speechend', 'soundend', 'audioend', 'result', 'nomatch', 'error', 'start', 'end', 'cognitiveservices'])); | ||
_this = (0, _possibleConstructorReturn2.default)(this, (0, _getPrototypeOf2.default)(SpeechRecognition).call(this)); | ||
_this._continuous = false; | ||
@@ -237,4 +288,6 @@ _this._interimResults = false; | ||
value: function emitCognitiveServices(type, event) { | ||
this.emit('cognitiveservices', _objectSpread({}, event, { | ||
subType: type | ||
this.dispatchEvent(new SpeechRecognitionEvent('cognitiveservices', { | ||
data: _objectSpread({}, event, { | ||
type: type | ||
}) | ||
})); | ||
@@ -251,6 +304,6 @@ } | ||
this._startOnce().catch(function (err) { | ||
_this2.emit('error', { | ||
_this2.dispatchEvent(new ErrorEvent('error', { | ||
error: err, | ||
message: err && err.message | ||
}); | ||
})); | ||
}); | ||
@@ -278,23 +331,11 @@ } | ||
queue = (0, _createPromiseQueue.default)(); | ||
// We modify "attach" function and detect when the first chunk is read. | ||
recognizer.audioConfig.attach = improviseAsync(recognizer.audioConfig.attach.bind(recognizer.audioConfig), function (reader) { | ||
var firstAudibleChunkEmitted; | ||
return _objectSpread({}, reader, { | ||
read: improviseAsync(reader.read.bind(reader), function (chunk) { | ||
// The magic number 150 is measured by: | ||
// 1. Set microphone volume to 0 | ||
// 2. Observe the amplitude (100-110) for the first few chunks | ||
// (This is short static caught when turning on the microphone) | ||
// 3. Set the number a bit higher than the observation | ||
if (!firstAudibleChunkEmitted && averageAmplitude(chunk.buffer) > 150) { | ||
queue.push({ | ||
firstAudibleChunk: {} | ||
}); | ||
firstAudibleChunkEmitted = true; | ||
} | ||
muted = false; | ||
return chunk; | ||
}) | ||
_onAudibleChunk = function onAudibleChunk() { | ||
queue.push({ | ||
firstAudibleChunk: {} | ||
}); | ||
}); | ||
_onAudibleChunk = null; | ||
}; | ||
_recognizer$audioConf = recognizer.audioConfig.events.attach(function (event) { | ||
@@ -314,7 +355,7 @@ var name = event.name; | ||
recognizer.canceled = function (_, _ref3) { | ||
var errorDetails = _ref3.errorDetails, | ||
offset = _ref3.offset, | ||
reason = _ref3.reason, | ||
sessionId = _ref3.sessionId; | ||
recognizer.canceled = function (_, _ref4) { | ||
var errorDetails = _ref4.errorDetails, | ||
offset = _ref4.offset, | ||
reason = _ref4.reason, | ||
sessionId = _ref4.sessionId; | ||
queue.push({ | ||
@@ -330,6 +371,6 @@ canceled: { | ||
recognizer.recognized = function (_, _ref4) { | ||
var offset = _ref4.offset, | ||
result = _ref4.result, | ||
sessionId = _ref4.sessionId; | ||
recognizer.recognized = function (_, _ref5) { | ||
var offset = _ref5.offset, | ||
result = _ref5.result, | ||
sessionId = _ref5.sessionId; | ||
queue.push({ | ||
@@ -344,6 +385,6 @@ recognized: { | ||
recognizer.recognizing = function (_, _ref5) { | ||
var offset = _ref5.offset, | ||
result = _ref5.result, | ||
sessionId = _ref5.sessionId; | ||
recognizer.recognizing = function (_, _ref6) { | ||
var offset = _ref6.offset, | ||
result = _ref6.result, | ||
sessionId = _ref6.sessionId; | ||
queue.push({ | ||
@@ -358,4 +399,4 @@ recognizing: { | ||
recognizer.sessionStarted = function (_, _ref6) { | ||
var sessionId = _ref6.sessionId; | ||
recognizer.sessionStarted = function (_, _ref7) { | ||
var sessionId = _ref7.sessionId; | ||
queue.push({ | ||
@@ -368,4 +409,4 @@ sessionStarted: { | ||
recognizer.sessionStopped = function (_, _ref7) { | ||
var sessionId = _ref7.sessionId; | ||
recognizer.sessionStopped = function (_, _ref8) { | ||
var sessionId = _ref8.sessionId; | ||
// "sessionStopped" is never fired, probably because we are using startContinuousRecognitionAsync instead of recognizeOnceAsync. | ||
@@ -379,5 +420,5 @@ queue.push({ | ||
recognizer.speechStartDetected = function (_, _ref8) { | ||
var offset = _ref8.offset, | ||
sessionId = _ref8.sessionId; | ||
recognizer.speechStartDetected = function (_, _ref9) { | ||
var offset = _ref9.offset, | ||
sessionId = _ref9.sessionId; | ||
queue.push({ | ||
@@ -391,4 +432,4 @@ speechStartDetected: { | ||
recognizer.speechEndDetected = function (_, _ref9) { | ||
var sessionId = _ref9.sessionId; | ||
recognizer.speechEndDetected = function (_, _ref10) { | ||
var sessionId = _ref10.sessionId; | ||
// "speechEndDetected" is never fired, probably because we are using startContinuousRecognitionAsync instead of recognizeOnceAsync. | ||
@@ -407,6 +448,6 @@ queue.push({ | ||
phrases && phrases.length && dynamicGrammar.addPhrase(phrases); | ||
_context3.next = 19; | ||
_context3.next = 20; | ||
return cognitiveServicesAsyncToPromise(recognizer.startContinuousRecognitionAsync.bind(recognizer))(); | ||
case 19: | ||
case 20: | ||
this.abort = function () { | ||
@@ -445,3 +486,3 @@ return queue.push({ | ||
if (!/Permission\sdenied/.test(errorMessage || '')) { | ||
if (!/Permission[\t-\r \xA0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF]denied/.test(errorMessage || '')) { | ||
_context2.next = 9; | ||
@@ -460,3 +501,3 @@ break; | ||
if (!loop) { | ||
_this3.emit('start'); | ||
_this3.dispatchEvent(new SpeechRecognitionEvent('start')); | ||
} | ||
@@ -471,5 +512,5 @@ | ||
if (!audioStarted) { | ||
_this3.emit('audiostart'); | ||
_this3.dispatchEvent(new SpeechRecognitionEvent('audiostart')); | ||
_this3.emit('audioend'); | ||
_this3.dispatchEvent(new SpeechRecognitionEvent('audioend')); | ||
} | ||
@@ -492,3 +533,3 @@ | ||
if (!(abort || stop)) { | ||
_context2.next = 22; | ||
_context2.next = 23; | ||
break; | ||
@@ -502,44 +543,48 @@ } | ||
}; | ||
} else if (finalizedResults.length) { | ||
finalEvent = { | ||
results: finalizedResults, | ||
type: 'result' | ||
}; | ||
} else { | ||
// When we set to mute and { isEnd: true }, Speech Services will send us "recognized" event. | ||
muted = true; | ||
} | ||
stopping = true; | ||
_context2.next = 20; | ||
if (!abort) { | ||
_context2.next = 21; | ||
break; | ||
} | ||
_context2.next = 21; | ||
return cognitiveServicesAsyncToPromise(recognizer.stopContinuousRecognitionAsync.bind(recognizer))(); | ||
case 20: | ||
_context2.next = 42; | ||
case 21: | ||
_context2.next = 43; | ||
break; | ||
case 22: | ||
case 23: | ||
if (!audioSourceReady) { | ||
_context2.next = 27; | ||
_context2.next = 28; | ||
break; | ||
} | ||
_this3.emit('audiostart'); | ||
_this3.dispatchEvent(new SpeechRecognitionEvent('audiostart')); | ||
audioStarted = true; | ||
_context2.next = 42; | ||
_context2.next = 43; | ||
break; | ||
case 27: | ||
case 28: | ||
if (!firstAudibleChunk) { | ||
_context2.next = 32; | ||
_context2.next = 33; | ||
break; | ||
} | ||
_this3.emit('soundstart'); | ||
_this3.dispatchEvent(new SpeechRecognitionEvent('soundstart')); | ||
soundStarted = true; | ||
_context2.next = 42; | ||
_context2.next = 43; | ||
break; | ||
case 32: | ||
case 33: | ||
if (!audioSourceOff) { | ||
_context2.next = 41; | ||
_context2.next = 42; | ||
break; | ||
@@ -549,9 +594,9 @@ } | ||
stopping = true; | ||
speechStarted && _this3.emit('speechend'); | ||
soundStarted && _this3.emit('soundend'); | ||
audioStarted && _this3.emit('audioend'); | ||
speechStarted && _this3.dispatchEvent(new SpeechRecognitionEvent('speechend')); | ||
soundStarted && _this3.dispatchEvent(new SpeechRecognitionEvent('soundend')); | ||
audioStarted && _this3.dispatchEvent(new SpeechRecognitionEvent('audioend')); | ||
audioStarted = soundStarted = speechStarted = false; | ||
return _context2.abrupt("return", "break"); | ||
case 41: | ||
case 42: | ||
if (recognized && recognized.result && recognized.result.reason === ResultReason.NoMatch) { | ||
@@ -565,3 +610,3 @@ finalEvent = { | ||
// Unconfirmed prevention of quirks | ||
_this3.emit('audiostart'); | ||
_this3.dispatchEvent(new SpeechRecognitionEvent('audiostart')); | ||
@@ -572,3 +617,3 @@ audioStarted = true; | ||
if (!soundStarted) { | ||
_this3.emit('soundstart'); | ||
_this3.dispatchEvent(new SpeechRecognitionEvent('soundstart')); | ||
@@ -579,3 +624,3 @@ soundStarted = true; | ||
if (!speechStarted) { | ||
_this3.emit('speechstart'); | ||
_this3.dispatchEvent(new SpeechRecognitionEvent('speechstart')); | ||
@@ -594,16 +639,17 @@ speechStarted = true; | ||
finalizedResults = [].concat((0, _toConsumableArray2.default)(finalizedResults), [result]); | ||
_this3.continuous && _this3.emit('result', { | ||
_this3.continuous && _this3.dispatchEvent(new SpeechRecognitionEvent('result', { | ||
results: finalizedResults | ||
}); | ||
})); | ||
} | ||
finalEvent = { | ||
results: finalizedResults, | ||
type: 'result' | ||
}; | ||
if (!_this3.continuous) { | ||
finalEvent = { | ||
results: finalizedResults, | ||
type: 'result' | ||
}; | ||
recognizer.stopContinuousRecognitionAsync(); | ||
} | ||
} else if (recognizing) { | ||
_this3.interimResults && _this3.emit('result', { | ||
_this3.interimResults && _this3.dispatchEvent(new SpeechRecognitionEvent('result', { | ||
results: [].concat((0, _toConsumableArray2.default)(finalizedResults), [(0, _cognitiveServiceEventResultToWebSpeechRecognitionResultList.default)(recognizing.result, { | ||
@@ -613,7 +659,7 @@ maxAlternatives: _this3.maxAlternatives, | ||
})]) | ||
}); | ||
})); | ||
} | ||
} | ||
case 42: | ||
case 43: | ||
case "end": | ||
@@ -627,36 +673,38 @@ return _context2.stop(); | ||
case 24: | ||
case 25: | ||
if (!(!stopping || audioStarted)) { | ||
_context3.next = 32; | ||
_context3.next = 33; | ||
break; | ||
} | ||
return _context3.delegateYield(_loop(loop), "t0", 26); | ||
return _context3.delegateYield(_loop(loop), "t0", 27); | ||
case 26: | ||
case 27: | ||
_ret = _context3.t0; | ||
if (!(_ret === "break")) { | ||
_context3.next = 29; | ||
_context3.next = 30; | ||
break; | ||
} | ||
return _context3.abrupt("break", 32); | ||
return _context3.abrupt("break", 33); | ||
case 29: | ||
case 30: | ||
loop++; | ||
_context3.next = 24; | ||
_context3.next = 25; | ||
break; | ||
case 32: | ||
case 33: | ||
_onAudibleChunk = null; | ||
if (speechStarted) { | ||
this.emit('speechend'); | ||
this.dispatchEvent(new SpeechRecognitionEvent('speechend')); | ||
} | ||
if (soundStarted) { | ||
this.emit('soundend'); | ||
this.dispatchEvent(new SpeechRecognitionEvent('soundend')); | ||
} | ||
if (audioStarted) { | ||
this.emit('audioend'); | ||
this.dispatchEvent(new SpeechRecognitionEvent('audioend')); | ||
} | ||
@@ -672,3 +720,7 @@ | ||
this.emit(finalEvent.type, finalEvent); | ||
if (finalEvent.type === 'error') { | ||
this.dispatchEvent(new ErrorEvent('error', finalEvent)); | ||
} else { | ||
this.dispatchEvent(new SpeechRecognitionEvent(finalEvent.type, finalEvent)); | ||
} | ||
} // Even though there is no "start" event emitted, we will still emit "end" event | ||
@@ -678,7 +730,7 @@ // This is mainly for "microphone blocked" story. | ||
this.emit('end'); | ||
this.dispatchEvent(new SpeechRecognitionEvent('end')); | ||
detachAudioConfigEvent(); | ||
recognizer.dispose(); | ||
case 39: | ||
case 41: | ||
case "end": | ||
@@ -746,7 +798,20 @@ return _context3.stop(); | ||
return SpeechRecognition; | ||
}(_DOMEventEmitter2.default); | ||
}(_eventTargetShim.EventTarget); | ||
(0, _eventTargetShim.defineEventAttribute)(SpeechRecognition.prototype, 'audioend'); | ||
(0, _eventTargetShim.defineEventAttribute)(SpeechRecognition.prototype, 'audiostart'); | ||
(0, _eventTargetShim.defineEventAttribute)(SpeechRecognition.prototype, 'cognitiveservices'); | ||
(0, _eventTargetShim.defineEventAttribute)(SpeechRecognition.prototype, 'end'); | ||
(0, _eventTargetShim.defineEventAttribute)(SpeechRecognition.prototype, 'error'); | ||
(0, _eventTargetShim.defineEventAttribute)(SpeechRecognition.prototype, 'nomatch'); | ||
(0, _eventTargetShim.defineEventAttribute)(SpeechRecognition.prototype, 'result'); | ||
(0, _eventTargetShim.defineEventAttribute)(SpeechRecognition.prototype, 'soundend'); | ||
(0, _eventTargetShim.defineEventAttribute)(SpeechRecognition.prototype, 'soundstart'); | ||
(0, _eventTargetShim.defineEventAttribute)(SpeechRecognition.prototype, 'speechend'); | ||
(0, _eventTargetShim.defineEventAttribute)(SpeechRecognition.prototype, 'speechstart'); | ||
(0, _eventTargetShim.defineEventAttribute)(SpeechRecognition.prototype, 'start'); | ||
return { | ||
SpeechGrammarList: _SpeechGrammarList.default, | ||
SpeechRecognition: SpeechRecognition | ||
SpeechRecognition: SpeechRecognition, | ||
SpeechRecognitionEvent: SpeechRecognitionEvent | ||
}; | ||
@@ -753,0 +818,0 @@ }; |
@@ -14,2 +14,3 @@ "use strict"; | ||
/* eslint class-methods-use-this: "off" */ | ||
var _default = | ||
@@ -16,0 +17,0 @@ /*#__PURE__*/ |
@@ -18,2 +18,3 @@ "use strict"; | ||
/* eslint no-await-in-loop: "off" */ | ||
var _default = | ||
@@ -20,0 +21,0 @@ /*#__PURE__*/ |
@@ -22,2 +22,3 @@ "use strict"; | ||
/* eslint no-await-in-loop: "off" */ | ||
var _default = | ||
@@ -24,0 +25,0 @@ /*#__PURE__*/ |
@@ -8,2 +8,3 @@ "use strict"; | ||
/* eslint no-magic-numbers: ["error", { "ignore": [0, 1, 100] }] */ | ||
// Cognitive Services does not support unsigned percentage | ||
@@ -22,4 +23,3 @@ // It must be converted into +/- first. | ||
function buildSSML(_ref) { | ||
var gender = _ref.gender, | ||
lang = _ref.lang, | ||
var lang = _ref.lang, | ||
_ref$pitch = _ref.pitch, | ||
@@ -32,4 +32,4 @@ pitch = _ref$pitch === void 0 ? 1 : _ref$pitch, | ||
volume = _ref.volume; | ||
return "<speak version=\"1.0\" xml:lang=\"".concat(lang, "\">\n <voice xml:lang=\"").concat(lang, "\" xml:gender=\"").concat(gender, "\" name=\"").concat(voice, "\">\n <prosody pitch=\"").concat(relativePercentage(pitch), "\" rate=\"").concat(relativePercentage(rate), "\" volume=\"").concat(relativePercentage(volume), "\">\n ").concat(text, "\n </prosody>\n </voice>\n</speak>"); | ||
return "<speak version=\"1.0\" xml:lang=\"".concat(lang, "\">\n <voice xml:lang=\"").concat(lang, "\" name=\"").concat(voice, "\">\n <prosody pitch=\"").concat(relativePercentage(pitch), "\" rate=\"").concat(relativePercentage(rate), "\" volume=\"").concat(relativePercentage(volume), "\">\n ").concat(text, "\n </prosody>\n </voice>\n</speak>"); | ||
} | ||
//# sourceMappingURL=buildSSML.js.map |
@@ -24,16 +24,24 @@ "use strict"; | ||
var _eventTargetShim = require("../../external/event-target-shim"); | ||
var _memoizeOne = _interopRequireDefault(require("memoize-one")); | ||
var _onErrorResumeNext = _interopRequireDefault(require("on-error-resume-next")); | ||
var _AudioContextQueue = _interopRequireDefault(require("./AudioContextQueue")); | ||
var _DOMEventEmitter2 = _interopRequireDefault(require("../../Util/DOMEventEmitter")); | ||
var _fetchAuthorizationToken = _interopRequireDefault(require("../fetchAuthorizationToken")); | ||
var _fetchCustomVoices = _interopRequireDefault(require("./fetchCustomVoices")); | ||
var _fetchVoices = _interopRequireDefault(require("./fetchVoices")); | ||
var _SpeechSynthesisEvent = _interopRequireDefault(require("./SpeechSynthesisEvent")); | ||
var _SpeechSynthesisUtterance = _interopRequireDefault(require("./SpeechSynthesisUtterance")); | ||
/* eslint class-methods-use-this: 0 */ | ||
// Supported output format can be found at https://docs.microsoft.com/en-us/azure/cognitive-services/speech-service/rest-text-to-speech#audio-outputs | ||
var DEFAULT_OUTPUT_FORMAT = 'audio-24khz-160kbitrate-mono-mp3'; | ||
var EMPTY_ARRAY = []; | ||
var TOKEN_EXPIRATION = 600000; | ||
@@ -57,6 +65,6 @@ var TOKEN_EARLY_RENEWAL = 60000; | ||
if (!authorizationToken && !subscriptionKey) { | ||
console.warn('Either authorization token or subscription key must be specified'); | ||
console.warn('web-speech-cognitive-services: Either authorization token or subscription key must be specified'); | ||
return {}; | ||
} else if (!ponyfill.AudioContext) { | ||
console.warn('This browser does not support Web Audio and it will not work with Cognitive Services Speech Services.'); | ||
console.warn('web-speech-cognitive-services: This browser does not support Web Audio and it will not work with Cognitive Services Speech Services.'); | ||
return {}; | ||
@@ -75,12 +83,15 @@ } | ||
}); | ||
var getAuthorizationTokenPromise = typeof authorizationToken === 'function' ? authorizationToken() : authorizationToken ? authorizationToken : fetchMemoizedAuthorizationToken({ | ||
now: Date.now, | ||
region: region, | ||
subscriptionKey: subscriptionKey | ||
}); | ||
var getAuthorizationToken = function getAuthorizationToken() { | ||
return typeof authorizationToken === 'function' ? authorizationToken() : authorizationToken ? authorizationToken : fetchMemoizedAuthorizationToken({ | ||
now: Date.now, | ||
region: region, | ||
subscriptionKey: subscriptionKey | ||
}); | ||
}; | ||
var SpeechSynthesis = | ||
/*#__PURE__*/ | ||
function (_DOMEventEmitter) { | ||
(0, _inherits2.default)(SpeechSynthesis, _DOMEventEmitter); | ||
function (_EventTarget) { | ||
(0, _inherits2.default)(SpeechSynthesis, _EventTarget); | ||
@@ -91,3 +102,3 @@ function SpeechSynthesis() { | ||
(0, _classCallCheck2.default)(this, SpeechSynthesis); | ||
_this = (0, _possibleConstructorReturn2.default)(this, (0, _getPrototypeOf2.default)(SpeechSynthesis).call(this, ['voiceschanged'])); | ||
_this = (0, _possibleConstructorReturn2.default)(this, (0, _getPrototypeOf2.default)(SpeechSynthesis).call(this)); | ||
_this.queue = new _AudioContextQueue.default({ | ||
@@ -97,3 +108,2 @@ audioContext: audioContext, | ||
}); | ||
_this.voices = []; | ||
@@ -113,3 +123,3 @@ _this.updateVoices(); | ||
value: function getVoices() { | ||
return this.voices; | ||
return EMPTY_ARRAY; | ||
} | ||
@@ -135,35 +145,14 @@ }, { | ||
return new Promise( | ||
/*#__PURE__*/ | ||
function () { | ||
var _ref3 = (0, _asyncToGenerator2.default)( | ||
/*#__PURE__*/ | ||
_regenerator.default.mark(function _callee(resolve, reject) { | ||
return _regenerator.default.wrap(function _callee$(_context) { | ||
while (1) { | ||
switch (_context.prev = _context.next) { | ||
case 0: | ||
utterance.addEventListener('end', resolve); | ||
utterance.addEventListener('error', reject); | ||
utterance.preload({ | ||
authorizationTokenPromise: getAuthorizationTokenPromise, | ||
deploymentId: speechSynthesisDeploymentId, | ||
outputFormat: speechSynthesisOutputFormat, | ||
region: region | ||
}); | ||
return new Promise(function (resolve, reject) { | ||
utterance.addEventListener('end', resolve); | ||
utterance.addEventListener('error', reject); | ||
utterance.preload({ | ||
deploymentId: speechSynthesisDeploymentId, | ||
getAuthorizationToken: getAuthorizationToken, | ||
outputFormat: speechSynthesisOutputFormat, | ||
region: region | ||
}); | ||
_this2.queue.push(utterance); | ||
case 4: | ||
case "end": | ||
return _context.stop(); | ||
} | ||
} | ||
}, _callee); | ||
})); | ||
return function (_x, _x2) { | ||
return _ref3.apply(this, arguments); | ||
}; | ||
}()); | ||
_this2.queue.push(utterance); | ||
}); | ||
} | ||
@@ -175,45 +164,109 @@ }, { | ||
/*#__PURE__*/ | ||
_regenerator.default.mark(function _callee2() { | ||
return _regenerator.default.wrap(function _callee2$(_context2) { | ||
_regenerator.default.mark(function _callee3() { | ||
var _this3 = this; | ||
return _regenerator.default.wrap(function _callee3$(_context3) { | ||
while (1) { | ||
switch (_context2.prev = _context2.next) { | ||
switch (_context3.prev = _context3.next) { | ||
case 0: | ||
if (speechSynthesisDeploymentId) { | ||
_context2.next = 17; | ||
if (!speechSynthesisDeploymentId) { | ||
_context3.next = 7; | ||
break; | ||
} | ||
_context2.prev = 1; | ||
_context2.t0 = _fetchVoices.default; | ||
_context2.next = 5; | ||
return getAuthorizationTokenPromise; | ||
if (!subscriptionKey) { | ||
_context3.next = 5; | ||
break; | ||
} | ||
console.warn('web-speech-cognitive-services: Listing of custom voice models are only available when using subscription key.'); | ||
_context3.next = 5; | ||
return (0, _onErrorResumeNext.default)( | ||
/*#__PURE__*/ | ||
(0, _asyncToGenerator2.default)( | ||
/*#__PURE__*/ | ||
_regenerator.default.mark(function _callee() { | ||
var voices; | ||
return _regenerator.default.wrap(function _callee$(_context) { | ||
while (1) { | ||
switch (_context.prev = _context.next) { | ||
case 0: | ||
_context.next = 2; | ||
return (0, _fetchCustomVoices.default)({ | ||
deploymentId: speechSynthesisDeploymentId, | ||
region: region, | ||
subscriptionKey: subscriptionKey | ||
}); | ||
case 2: | ||
voices = _context.sent; | ||
_this3.getVoices = function () { | ||
return voices; | ||
}; | ||
case 4: | ||
case "end": | ||
return _context.stop(); | ||
} | ||
} | ||
}, _callee); | ||
}))); | ||
case 5: | ||
_context2.t1 = _context2.sent; | ||
_context2.t2 = speechSynthesisDeploymentId; | ||
_context2.t3 = region; | ||
_context2.t4 = { | ||
authorizationToken: _context2.t1, | ||
deploymentId: _context2.t2, | ||
region: _context2.t3 | ||
}; | ||
_context2.next = 11; | ||
return (0, _context2.t0)(_context2.t4); | ||
case 11: | ||
this.voices = _context2.sent; | ||
this.emit('voiceschanged'); | ||
_context2.next = 17; | ||
_context3.next = 9; | ||
break; | ||
case 15: | ||
_context2.prev = 15; | ||
_context2.t5 = _context2["catch"](1); | ||
case 7: | ||
_context3.next = 9; | ||
return (0, _onErrorResumeNext.default)( | ||
/*#__PURE__*/ | ||
(0, _asyncToGenerator2.default)( | ||
/*#__PURE__*/ | ||
_regenerator.default.mark(function _callee2() { | ||
var voices; | ||
return _regenerator.default.wrap(function _callee2$(_context2) { | ||
while (1) { | ||
switch (_context2.prev = _context2.next) { | ||
case 0: | ||
_context2.t0 = _fetchVoices.default; | ||
_context2.next = 3; | ||
return getAuthorizationToken(); | ||
case 17: | ||
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 9: | ||
voices = _context2.sent; | ||
_this3.getVoices = function () { | ||
return voices; | ||
}; | ||
case 11: | ||
case "end": | ||
return _context2.stop(); | ||
} | ||
} | ||
}, _callee2); | ||
}))); | ||
case 9: | ||
this.dispatchEvent(new _SpeechSynthesisEvent.default('voiceschanged')); | ||
case 10: | ||
case "end": | ||
return _context2.stop(); | ||
return _context3.stop(); | ||
} | ||
} | ||
}, _callee2, this, [[1, 15]]); | ||
}, _callee3, this); | ||
})); | ||
@@ -234,6 +287,8 @@ | ||
return SpeechSynthesis; | ||
}(_DOMEventEmitter2.default); | ||
}(_eventTargetShim.EventTarget); | ||
(0, _eventTargetShim.defineEventAttribute)(SpeechSynthesis.prototype, 'voiceschanged'); | ||
return { | ||
speechSynthesis: new SpeechSynthesis(), | ||
SpeechSynthesisEvent: _SpeechSynthesisEvent.default, | ||
SpeechSynthesisUtterance: _SpeechSynthesisUtterance.default | ||
@@ -240,0 +295,0 @@ }; |
@@ -18,2 +18,4 @@ "use strict"; | ||
var _isSSML = _interopRequireDefault(require("./isSSML")); | ||
var DEFAULT_LANGUAGE = 'en-US'; | ||
@@ -33,3 +35,3 @@ var DEFAULT_VOICE = 'Microsoft Server Speech Text to Speech Voice (en-US, JessaRUS)'; | ||
_regenerator.default.mark(function _callee(_ref) { | ||
var authorizationTokenPromise, deploymentId, _ref$lang, lang, outputFormat, pitch, rate, region, text, _ref$voice, voice, volume, authorizationToken, ssml, url, res; | ||
var deploymentId, getAuthorizationToken, _ref$lang, lang, outputFormat, pitch, rate, region, text, _ref$voice, voice, volume, authorizationToken, ssml, url, res; | ||
@@ -40,3 +42,3 @@ return _regenerator.default.wrap(function _callee$(_context) { | ||
case 0: | ||
authorizationTokenPromise = _ref.authorizationTokenPromise, deploymentId = _ref.deploymentId, _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, 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; | ||
@@ -52,7 +54,7 @@ if (text) { | ||
_context.next = 5; | ||
return authorizationTokenPromise; | ||
return getAuthorizationToken(); | ||
case 5: | ||
authorizationToken = _context.sent; | ||
ssml = (0, _buildSSML.default)({ | ||
ssml = (0, _isSSML.default)(text) ? text : (0, _buildSSML.default)({ | ||
lang: lang, | ||
@@ -81,3 +83,3 @@ pitch: pitch, | ||
if (!(res.status !== 200)) { | ||
if (res.ok) { | ||
_context.next = 13; | ||
@@ -84,0 +86,0 @@ break; |
@@ -16,2 +16,3 @@ "use strict"; | ||
/* eslint no-magic-numbers: ["error", { "ignore": [0, 1, -1] }] */ | ||
function _default(_x) { | ||
@@ -25,3 +26,3 @@ return _ref2.apply(this, arguments); | ||
_regenerator.default.mark(function _callee(_ref) { | ||
var authorizationToken, deploymentId, region, res, voices; | ||
var authorizationToken, region, res, voices; | ||
return _regenerator.default.wrap(function _callee$(_context) { | ||
@@ -31,5 +32,5 @@ while (1) { | ||
case 0: | ||
authorizationToken = _ref.authorizationToken, deploymentId = _ref.deploymentId, region = _ref.region; | ||
authorizationToken = _ref.authorizationToken, region = _ref.region; | ||
_context.next = 3; | ||
return fetch(deploymentId ? "https://".concat(encodeURI(region), ".voice.speech.microsoft.com/cognitiveservices/voices/list?deploymentId=").concat(encodeURIComponent(deploymentId)) : "https://".concat(encodeURI(region), ".tts.speech.microsoft.com/cognitiveservices/voices/list"), { | ||
return fetch("https://".concat(encodeURI(region), ".tts.speech.microsoft.com/cognitiveservices/voices/list"), { | ||
headers: { | ||
@@ -36,0 +37,0 @@ authorization: "Bearer ".concat(authorizationToken), |
@@ -10,2 +10,6 @@ "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")); | ||
@@ -21,14 +25,13 @@ | ||
var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator")); | ||
var _eventTargetShim = require("../../external/event-target-shim"); | ||
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator")); | ||
var _eventAsPromise = _interopRequireDefault(require("event-as-promise")); | ||
var _DOMEventEmitter2 = _interopRequireDefault(require("../../Util/DOMEventEmitter")); | ||
var _fetchSpeechData = _interopRequireDefault(require("./fetchSpeechData")); | ||
var _SpeechSynthesisEvent = _interopRequireDefault(require("./SpeechSynthesisEvent")); | ||
var _subscribeEvent = _interopRequireDefault(require("./subscribeEvent")); | ||
/* eslint no-empty: ["error", { "allowEmptyCatch": true }] */ | ||
function asyncDecodeAudioData(audioContext, arrayBuffer) { | ||
@@ -43,67 +46,35 @@ return new Promise(function (resolve, reject) { | ||
function playDecoded(audioContext, audioBuffer, source) { | ||
return new Promise( | ||
/*#__PURE__*/ | ||
function () { | ||
var _ref = (0, _asyncToGenerator2.default)( | ||
/*#__PURE__*/ | ||
_regenerator.default.mark(function _callee(resolve, reject) { | ||
var audioContextClosed, sourceEnded, unsubscribe; | ||
return _regenerator.default.wrap(function _callee$(_context) { | ||
while (1) { | ||
switch (_context.prev = _context.next) { | ||
case 0: | ||
audioContextClosed = new _eventAsPromise.default(); | ||
sourceEnded = new _eventAsPromise.default(); | ||
unsubscribe = (0, _subscribeEvent.default)(audioContext, 'statechange', function (_ref2) { | ||
var state = _ref2.target.state; | ||
return state === 'closed' && audioContextClosed.eventListener(); | ||
}); | ||
_context.prev = 3; | ||
source.buffer = audioBuffer; // "ended" may not fire if the underlying AudioContext is closed prematurely | ||
return new Promise(function (resolve, reject) { | ||
var audioContextClosed = new _eventAsPromise.default(); | ||
var sourceEnded = new _eventAsPromise.default(); | ||
var unsubscribe = (0, _subscribeEvent.default)(audioContext, 'statechange', function (_ref) { | ||
var state = _ref.target.state; | ||
return state === 'closed' && audioContextClosed.eventListener(); | ||
}); | ||
source.onended = sourceEnded.eventListener; | ||
source.connect(audioContext.destination); | ||
source.start(0); | ||
_context.next = 10; | ||
return Promise.race([audioContextClosed.upcoming(), sourceEnded.upcoming()]); | ||
try { | ||
source.buffer = audioBuffer; // "ended" may not fire if the underlying AudioContext is closed prematurely | ||
case 10: | ||
resolve(); | ||
_context.next = 16; | ||
break; | ||
case 13: | ||
_context.prev = 13; | ||
_context.t0 = _context["catch"](3); | ||
reject(_context.t0); | ||
case 16: | ||
_context.prev = 16; | ||
unsubscribe(); | ||
return _context.finish(16); | ||
case 19: | ||
case "end": | ||
return _context.stop(); | ||
} | ||
} | ||
}, _callee, null, [[3, 13, 16, 19]]); | ||
})); | ||
return function (_x, _x2) { | ||
return _ref.apply(this, arguments); | ||
}; | ||
}()); | ||
source.onended = sourceEnded.eventListener; | ||
source.connect(audioContext.destination); | ||
source.start(0); | ||
Promise.race([audioContextClosed.upcoming(), sourceEnded.upcoming()]).then(resolve); | ||
} catch (err) { | ||
reject(err); | ||
} finally { | ||
unsubscribe(); | ||
} | ||
}); | ||
} | ||
var _default = | ||
var SpeechSynthesisUtterance = | ||
/*#__PURE__*/ | ||
function (_DOMEventEmitter) { | ||
(0, _inherits2.default)(_default, _DOMEventEmitter); | ||
function (_EventTarget) { | ||
(0, _inherits2.default)(SpeechSynthesisUtterance, _EventTarget); | ||
function _default(text) { | ||
function SpeechSynthesisUtterance(text) { | ||
var _this; | ||
(0, _classCallCheck2.default)(this, _default); | ||
_this = (0, _possibleConstructorReturn2.default)(this, (0, _getPrototypeOf2.default)(_default).call(this, ['boundary', 'end', 'error', 'mark', 'pause', 'resume', 'start'])); | ||
(0, _classCallCheck2.default)(this, SpeechSynthesisUtterance); | ||
_this = (0, _possibleConstructorReturn2.default)(this, (0, _getPrototypeOf2.default)(SpeechSynthesisUtterance).call(this)); | ||
_this._lang = null; | ||
@@ -125,3 +96,3 @@ _this._pitch = 1; | ||
(0, _createClass2.default)(_default, [{ | ||
(0, _createClass2.default)(SpeechSynthesisUtterance, [{ | ||
key: "preload", | ||
@@ -131,12 +102,12 @@ value: function () { | ||
/*#__PURE__*/ | ||
_regenerator.default.mark(function _callee2(_ref3) { | ||
var authorizationTokenPromise, deploymentId, outputFormat, region; | ||
return _regenerator.default.wrap(function _callee2$(_context2) { | ||
_regenerator.default.mark(function _callee(_ref2) { | ||
var deploymentId, getAuthorizationToken, outputFormat, region; | ||
return _regenerator.default.wrap(function _callee$(_context) { | ||
while (1) { | ||
switch (_context2.prev = _context2.next) { | ||
switch (_context.prev = _context.next) { | ||
case 0: | ||
authorizationTokenPromise = _ref3.authorizationTokenPromise, deploymentId = _ref3.deploymentId, outputFormat = _ref3.outputFormat, region = _ref3.region; | ||
deploymentId = _ref2.deploymentId, getAuthorizationToken = _ref2.getAuthorizationToken, outputFormat = _ref2.outputFormat, region = _ref2.region; | ||
this.arrayBufferPromise = (0, _fetchSpeechData.default)({ | ||
authorizationTokenPromise: authorizationTokenPromise, | ||
deploymentId: deploymentId, | ||
getAuthorizationToken: getAuthorizationToken, | ||
lang: this.lang || window.navigator.language, | ||
@@ -153,23 +124,23 @@ outputFormat: outputFormat, | ||
_context2.prev = 2; | ||
_context2.next = 5; | ||
_context.prev = 2; | ||
_context.next = 5; | ||
return this.arrayBufferPromise; | ||
case 5: | ||
_context2.next = 9; | ||
_context.next = 9; | ||
break; | ||
case 7: | ||
_context2.prev = 7; | ||
_context2.t0 = _context2["catch"](2); | ||
_context.prev = 7; | ||
_context.t0 = _context["catch"](2); | ||
case 9: | ||
case "end": | ||
return _context2.stop(); | ||
return _context.stop(); | ||
} | ||
} | ||
}, _callee2, this, [[2, 7]]); | ||
}, _callee, this, [[2, 7]]); | ||
})); | ||
function preload(_x3) { | ||
function preload(_x) { | ||
return _preload.apply(this, arguments); | ||
@@ -185,27 +156,27 @@ } | ||
/*#__PURE__*/ | ||
_regenerator.default.mark(function _callee3(audioContext) { | ||
_regenerator.default.mark(function _callee2(audioContext) { | ||
var source, audioBuffer; | ||
return _regenerator.default.wrap(function _callee3$(_context3) { | ||
return _regenerator.default.wrap(function _callee2$(_context2) { | ||
while (1) { | ||
switch (_context3.prev = _context3.next) { | ||
switch (_context2.prev = _context2.next) { | ||
case 0: | ||
_context3.prev = 0; | ||
_context2.prev = 0; | ||
// We should emit "start" event even if preload() failed. | ||
this.emit('start'); // HACK: iOS requires bufferSourceNode to be constructed before decoding data. | ||
this.dispatchEvent(new _SpeechSynthesisEvent.default('start')); // HACK: iOS requires bufferSourceNode to be constructed before decoding data. | ||
source = audioContext.createBufferSource(); | ||
_context3.t0 = asyncDecodeAudioData; | ||
_context3.t1 = audioContext; | ||
_context3.next = 7; | ||
_context2.t0 = asyncDecodeAudioData; | ||
_context2.t1 = audioContext; | ||
_context2.next = 7; | ||
return this.arrayBufferPromise; | ||
case 7: | ||
_context3.t2 = _context3.sent; | ||
_context3.next = 10; | ||
return (0, _context3.t0)(_context3.t1, _context3.t2); | ||
_context2.t2 = _context2.sent; | ||
_context2.next = 10; | ||
return (0, _context2.t0)(_context2.t1, _context2.t2); | ||
case 10: | ||
audioBuffer = _context3.sent; | ||
audioBuffer = _context2.sent; | ||
this._playingSource = source; | ||
_context3.next = 14; | ||
_context2.next = 14; | ||
return playDecoded(audioContext, audioBuffer, source); | ||
@@ -215,22 +186,22 @@ | ||
this._playingSource = null; | ||
this.emit('end'); | ||
_context3.next = 21; | ||
this.dispatchEvent(new _SpeechSynthesisEvent.default('end')); | ||
_context2.next = 21; | ||
break; | ||
case 18: | ||
_context3.prev = 18; | ||
_context3.t3 = _context3["catch"](0); | ||
this.emit('error', { | ||
error: _context3.t3 | ||
}); | ||
_context2.prev = 18; | ||
_context2.t3 = _context2["catch"](0); | ||
this.dispatchEvent(new ErrorEvent('error', { | ||
error: _context2.t3 | ||
})); | ||
case 21: | ||
case "end": | ||
return _context3.stop(); | ||
return _context2.stop(); | ||
} | ||
} | ||
}, _callee3, this, [[0, 18]]); | ||
}, _callee2, this, [[0, 18]]); | ||
})); | ||
function play(_x4) { | ||
function play(_x2) { | ||
return _play.apply(this, arguments); | ||
@@ -287,6 +258,14 @@ } | ||
}]); | ||
return _default; | ||
}(_DOMEventEmitter2.default); | ||
return SpeechSynthesisUtterance; | ||
}(_eventTargetShim.EventTarget); | ||
(0, _eventTargetShim.defineEventAttribute)(SpeechSynthesisUtterance.prototype, 'boundary'); | ||
(0, _eventTargetShim.defineEventAttribute)(SpeechSynthesisUtterance.prototype, 'end'); | ||
(0, _eventTargetShim.defineEventAttribute)(SpeechSynthesisUtterance.prototype, 'error'); | ||
(0, _eventTargetShim.defineEventAttribute)(SpeechSynthesisUtterance.prototype, 'mark'); | ||
(0, _eventTargetShim.defineEventAttribute)(SpeechSynthesisUtterance.prototype, 'pause'); | ||
(0, _eventTargetShim.defineEventAttribute)(SpeechSynthesisUtterance.prototype, 'resume'); | ||
(0, _eventTargetShim.defineEventAttribute)(SpeechSynthesisUtterance.prototype, 'start'); | ||
var _default = SpeechSynthesisUtterance; | ||
exports.default = _default; | ||
//# sourceMappingURL=SpeechSynthesisUtterance.js.map |
@@ -22,4 +22,6 @@ "use strict"; | ||
(0, _classCallCheck2.default)(this, _default); | ||
this._default = false; | ||
this._gender = gender; | ||
this._lang = lang; | ||
this._localService = false; | ||
this._name = voiceURI; | ||
@@ -32,3 +34,3 @@ this._voiceURI = voiceURI; | ||
get: function get() { | ||
return false; | ||
return this._default; | ||
} | ||
@@ -48,3 +50,3 @@ }, { | ||
get: function get() { | ||
return false; | ||
return this._localService; | ||
} | ||
@@ -51,0 +53,0 @@ }, { |
@@ -32,3 +32,8 @@ // The MIT License (MIT) | ||
module.exports = function () { | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.default = createDeferred; | ||
function createDeferred() { | ||
var ret = {}; | ||
@@ -40,3 +45,3 @@ ret.promise = new Promise(function (resolve, reject) { | ||
return ret; | ||
}; | ||
} | ||
//# sourceMappingURL=createDeferred.js.map |
@@ -30,5 +30,5 @@ "use strict"; | ||
return Promise.resolve(queue.shift()); | ||
} else { | ||
return (shiftDeferred || (shiftDeferred = (0, _createDeferred.default)())).promise; | ||
} | ||
return (shiftDeferred || (shiftDeferred = (0, _createDeferred.default)())).promise; | ||
}; | ||
@@ -35,0 +35,0 @@ |
{ | ||
"name": "web-speech-cognitive-services", | ||
"version": "4.0.1-master.fcd6f40", | ||
"version": "5.0.0-master.edfd25f", | ||
"description": "Polyfill Web Speech API with Cognitive Services Speech-to-Text service", | ||
@@ -34,2 +34,4 @@ "keywords": [ | ||
"clean": "rimraf lib", | ||
"eslint": "eslint src/**/*.js", | ||
"prepublishOnly": "npm run eslint && npm run build", | ||
"start": "npm run build -- --verbose --watch", | ||
@@ -73,8 +75,11 @@ "test": "jest" | ||
"base64-arraybuffer": "^0.2.0", | ||
"eslint": "^6.1.0", | ||
"event-as-promise": "^1.0.5", | ||
"event-target-shim": "^5.0.1", | ||
"events": "^3.0.0", | ||
"memoize-one": "^5.0.5", | ||
"microsoft-cognitiveservices-speech-sdk": "1.6.0", | ||
"on-error-resume-next": "^1.1.0", | ||
"simple-update-in": "^2.1.0" | ||
} | ||
} |
@@ -9,16 +9,18 @@ # web-speech-cognitive-services | ||
# Demo | ||
# Description | ||
Try out our demo at https://compulim.github.io/web-speech-cognitive-services?s=your-subscription-key. | ||
Speech technologies enables a lot of interesting scenarios, including Intelligent Personal Assistant and provide alternative inputs for assistive technologies. | ||
We use [`react-dictate-button`](https://github.com/compulim/react-dictate-button/) and [`react-say`](https://github.com/compulim/react-say/) to quickly setup the playground. | ||
Although W3C standardized speech technologies in browser, speech-to-text and text-to-speech support are still scarce. However, cloud-based speech technologies are very mature. | ||
# Background | ||
This polyfill provides W3C [Speech Recognition](https://developer.mozilla.org/en-US/docs/Web/API/SpeechRecognition) and [Speech Synthesis](https://developer.mozilla.org/en-US/docs/Web/API/SpeechSynthesis) API in browser by using [Azure Cognitive Services Speech Services](https://azure.microsoft.com/en-us/services/cognitive-services/speech-services/). This will bring speech technologies to all modern first-party browsers available on both PC and mobile platforms. | ||
Web Speech API is not widely adopted on popular browsers and platforms. Polyfilling the API using cloud services is a great way to enable wider adoption. Nonetheless, Web Speech API in Google Chrome is also backed by cloud services. | ||
# Demo | ||
Microsoft Azure [Cognitive Services Speech Services](https://azure.microsoft.com/en-us/services/cognitive-services/speech-services/) service provide speech recognition with great accuracy. But unfortunately, the APIs are not based on Web Speech API. | ||
> Before getting started, please obtain a Cognitive Services subscription key from your Azure subscription. | ||
This package will polyfill Web Speech API by turning Cognitive Services Speech Services API into Web Speech API. We test this package with popular combination of platforms and browsers. | ||
Try out our demo at https://compulim.github.io/web-speech-cognitive-services. If you don't have a subscription key, you can still try out our demo in a speech-supported browser. | ||
We use [`react-dictate-button`](https://github.com/compulim/react-dictate-button/) and [`react-say`](https://github.com/compulim/react-say/) to quickly setup the playground. | ||
## Browser requirements | ||
@@ -28,4 +30,6 @@ | ||
Speech synthesis requires Web Audio API. For Safari, user gesture (click or tap) is required to play audio clips using Web Audio API. To ready the Web Audio API to use without user gesture, you can synthesize an empty string. | ||
### Special requirement for Safari | ||
Speech synthesis requires Web Audio API. For Safari, user gesture (click or tap) is required to play audio clips using Web Audio API. To ready the Web Audio API to use without user gesture, you can synthesize an empty string, which will not trigger any network calls but playing an empty hardcoded short audio clip. If you already have a "primed" `AudioContext` object, you can also pass it as an option. | ||
# How to use | ||
@@ -72,2 +76,4 @@ | ||
The `voiceschanged` event come shortly after you created the ponyfill. You will need to wait until the event arrived before able to choose a voice for your utterance. | ||
## Install from NPM | ||
@@ -131,2 +137,7 @@ | ||
<tr> | ||
<td><code>enableTelemetry</code></td> | ||
<td><code>undefined</code></td> | ||
<td>Pass-through option to enable or disable telemetry for Speech SDK recognizer as <a href="https://github.com/Microsoft/cognitive-services-speech-sdk-js#data--telemetry">outlined in Speech SDK</a>. This adapter does not collect any telemetry.<br /><br />By default, Speech SDK will collect telemetry unless this is set to <code>false</code>.</td> | ||
</tr> | ||
<tr> | ||
<td><code>ponyfill.AudioContext: <a href="https://developer.mozilla.org/en-US/docs/Web/API/AudioContext">AudioContext</a></code></td> | ||
@@ -249,35 +260,2 @@ <td><code>window.AudioContext ||</code><br /><code>window.webkitAudioContext</code></td> | ||
### Speech priming (a.k.a. grammars) | ||
> This section is currently not implemented with new Speech SDK. We are leaving the section here for future reference. | ||
You can prime the speech recognition by giving a list of words. | ||
Since Cognitive Services does not works with weighted grammars, we built another `SpeechGrammarList` to better fit the scenario. | ||
```jsx | ||
import createPonyfill from 'web-speech-cognitive-services/lib/SpeechServices'; | ||
const { | ||
SpeechGrammarList, | ||
SpeechRecognition | ||
} = await createPonyfill({ | ||
region: 'westus', | ||
subscriptionKey: 'YOUR_SUBSCRIPTION_KEY' | ||
}); | ||
const recognition = new SpeechRecognition(); | ||
recognition.grammars = new SpeechGrammarList(); | ||
recognition.grammars.phrases = ['Tuen Mun', 'Yuen Long']; | ||
recognition.onresult = ({ results }) => { | ||
console.log(results); | ||
}; | ||
recognition.start(); | ||
``` | ||
> Note: you can also pass `grammars` to `react-dictate-button` via `extra` props. | ||
## Speech synthesis (text-to-speech) | ||
@@ -388,2 +366,31 @@ | ||
## Biasing towards some words for recognition | ||
In some cases, you may want the speech recognition engine to be biased towards "Bellevue" because it is not trivial for the engine to recognize between "Bellevue", "Bellview" and "Bellvue" (without "e"). By giving a list of words, teh speech recognition engine will be more biased to your choice of words. | ||
Since Cognitive Services does not works with weighted grammars, we built another `SpeechGrammarList` to better fit the scenario. | ||
```jsx | ||
import createPonyfill from 'web-speech-cognitive-services/lib/SpeechServices'; | ||
const { | ||
SpeechGrammarList, | ||
SpeechRecognition | ||
} = await createPonyfill({ | ||
region: 'westus', | ||
subscriptionKey: 'YOUR_SUBSCRIPTION_KEY' | ||
}); | ||
const recognition = new SpeechRecognition(); | ||
recognition.grammars = new SpeechGrammarList(); | ||
recognition.grammars.phrases = ['Tuen Mun', 'Yuen Long']; | ||
recognition.onresult = ({ results }) => { | ||
console.log(results); | ||
}; | ||
recognition.start(); | ||
``` | ||
## Custom Speech support | ||
@@ -440,8 +447,5 @@ | ||
* Although Google Chrome support grammar list, it seems the grammar list is not used at all | ||
* Continuous mode | ||
* `stop()` is same as `abort()` | ||
* If `stop()` is called before first `recognized` event, there will be no final result | ||
* Speech synthesis | ||
* `onboundary`, `onmark`, `onpause`, and `onresume` are not supported/fired | ||
* `pause` will pause immediately and do not pause on word breaks | ||
* `pause` will pause immediately and do not pause on word breaks due to lack of boundary | ||
@@ -448,0 +452,0 @@ # Roadmap |
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 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
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
4274056
95
9010
469
12
10
+ Addedeslint@^6.1.0
+ Addedevent-target-shim@^5.0.1
+ Addedon-error-resume-next@^1.1.0
+ Added@babel/code-frame@7.26.2(transitive)
+ Added@babel/helper-validator-identifier@7.25.9(transitive)
+ Addedacorn@7.4.1(transitive)
+ Addedacorn-jsx@5.3.2(transitive)
+ Addedajv@6.12.6(transitive)
+ Addedansi-escapes@4.3.2(transitive)
+ Addedansi-regex@4.1.15.0.1(transitive)
+ Addedansi-styles@3.2.14.3.0(transitive)
+ Addedargparse@1.0.10(transitive)
+ Addedastral-regex@1.0.0(transitive)
+ Addedbalanced-match@1.0.2(transitive)
+ Addedbrace-expansion@1.1.11(transitive)
+ Addedcallsites@3.1.0(transitive)
+ Addedchalk@2.4.24.1.2(transitive)
+ Addedchardet@0.7.0(transitive)
+ Addedcli-cursor@3.1.0(transitive)
+ Addedcli-width@3.0.0(transitive)
+ Addedcolor-convert@1.9.32.0.1(transitive)
+ Addedcolor-name@1.1.31.1.4(transitive)
+ Addedconcat-map@0.0.1(transitive)
+ Addedcross-spawn@6.0.6(transitive)
+ Addeddebug@4.3.7(transitive)
+ Addeddeep-is@0.1.4(transitive)
+ Addeddoctrine@3.0.0(transitive)
+ Addedemoji-regex@7.0.38.0.0(transitive)
+ Addedescape-string-regexp@1.0.5(transitive)
+ Addedeslint@6.8.0(transitive)
+ Addedeslint-scope@5.1.1(transitive)
+ Addedeslint-utils@1.4.3(transitive)
+ Addedeslint-visitor-keys@1.3.0(transitive)
+ Addedespree@6.2.1(transitive)
+ Addedesprima@4.0.1(transitive)
+ Addedesquery@1.6.0(transitive)
+ Addedesrecurse@4.3.0(transitive)
+ Addedestraverse@4.3.05.3.0(transitive)
+ Addedesutils@2.0.3(transitive)
+ Addedevent-target-shim@5.0.1(transitive)
+ Addedexternal-editor@3.1.0(transitive)
+ Addedfast-deep-equal@3.1.3(transitive)
+ Addedfast-json-stable-stringify@2.1.0(transitive)
+ Addedfast-levenshtein@2.0.6(transitive)
+ Addedfigures@3.2.0(transitive)
+ Addedfile-entry-cache@5.0.1(transitive)
+ Addedflat-cache@2.0.1(transitive)
+ Addedflatted@2.0.2(transitive)
+ Addedfs.realpath@1.0.0(transitive)
+ Addedfunctional-red-black-tree@1.0.1(transitive)
+ Addedglob@7.2.3(transitive)
+ Addedglob-parent@5.1.2(transitive)
+ Addedglobals@12.4.0(transitive)
+ Addedhas-flag@3.0.04.0.0(transitive)
+ Addediconv-lite@0.4.24(transitive)
+ Addedignore@4.0.6(transitive)
+ Addedimport-fresh@3.3.0(transitive)
+ Addedimurmurhash@0.1.4(transitive)
+ Addedinflight@1.0.6(transitive)
+ Addedinquirer@7.3.3(transitive)
+ Addedis-extglob@2.1.1(transitive)
+ Addedis-fullwidth-code-point@2.0.03.0.0(transitive)
+ Addedis-glob@4.0.3(transitive)
+ Addedisexe@2.0.0(transitive)
+ Addedjs-yaml@3.14.1(transitive)
+ Addedjson-schema-traverse@0.4.1(transitive)
+ Addedjson-stable-stringify-without-jsonify@1.0.1(transitive)
+ Addedlevn@0.3.0(transitive)
+ Addedlodash@4.17.21(transitive)
+ Addedmimic-fn@2.1.0(transitive)
+ Addedminimatch@3.1.2(transitive)
+ Addedminimist@1.2.8(transitive)
+ Addedmkdirp@0.5.6(transitive)
+ Addedmute-stream@0.0.8(transitive)
+ Addednatural-compare@1.4.0(transitive)
+ Addednice-try@1.0.5(transitive)
+ Addedon-error-resume-next@1.2.0(transitive)
+ Addedonce@1.4.0(transitive)
+ Addedonetime@5.1.2(transitive)
+ Addedoptionator@0.8.3(transitive)
+ Addedos-tmpdir@1.0.2(transitive)
+ Addedparent-module@1.0.1(transitive)
+ Addedpath-is-absolute@1.0.1(transitive)
+ Addedpath-key@2.0.1(transitive)
+ Addedpicocolors@1.1.1(transitive)
+ Addedprelude-ls@1.1.2(transitive)
+ Addedprogress@2.0.3(transitive)
+ Addedpunycode@2.3.1(transitive)
+ Addedregexpp@2.0.1(transitive)
+ Addedresolve-from@4.0.0(transitive)
+ Addedrestore-cursor@3.1.0(transitive)
+ Addedrimraf@2.6.3(transitive)
+ Addedrun-async@2.4.1(transitive)
+ Addedrxjs@6.6.7(transitive)
+ Addedsemver@5.7.26.3.1(transitive)
+ Addedshebang-command@1.2.0(transitive)
+ Addedshebang-regex@1.0.0(transitive)
+ Addedsignal-exit@3.0.7(transitive)
+ Addedslice-ansi@2.1.0(transitive)
+ Addedsprintf-js@1.0.3(transitive)
+ Addedstring-width@3.1.04.2.3(transitive)
+ Addedstrip-ansi@5.2.06.0.1(transitive)
+ Addedstrip-json-comments@3.1.1(transitive)
+ Addedsupports-color@5.5.07.2.0(transitive)
+ Addedtable@5.4.6(transitive)
+ Addedtext-table@0.2.0(transitive)
+ Addedthrough@2.3.8(transitive)
+ Addedtmp@0.0.33(transitive)
+ Addedtslib@1.14.1(transitive)
+ Addedtype-check@0.3.2(transitive)
+ Addedtype-fest@0.21.30.8.1(transitive)
+ Addeduri-js@4.4.1(transitive)
+ Addedv8-compile-cache@2.4.0(transitive)
+ Addedwhich@1.3.1(transitive)
+ Addedword-wrap@1.2.5(transitive)
+ Addedwrappy@1.0.2(transitive)
+ Addedwrite@1.0.3(transitive)