UNPKG

@aurally/speech-control

Version:

A class to handle microphone permissions, start and observe speech input

146 lines 6.23 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var rxjs_1 = require("rxjs"); var operators_1 = require("rxjs/operators"); var notification_1 = require("./components/notification"); var SpeechControlErrors; (function (SpeechControlErrors) { SpeechControlErrors["NoSpeechRecognition"] = "no-speech-recognition"; SpeechControlErrors["Disabled"] = "disabled"; })(SpeechControlErrors = exports.SpeechControlErrors || (exports.SpeechControlErrors = {})); var SpeechControl = /** @class */ (function () { function SpeechControl(options) { this._stopped = false; this._notificationShown = false; this.recLanguage = options && options.recLanguage; this.notification = {}; } SpeechControl.prototype._record = function (subscriber) { var SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition; this._recognition = new SpeechRecognition(); if (this._recognition) { // this._recognition.continuous = true if (this.recLanguage) { this._recognition.lang = this.recLanguage; } this._recognition.onresult = subscriber.next.bind(subscriber); this._recognition.onend = subscriber.complete.bind(subscriber); this._recognition.onerror = subscriber.error.bind(subscriber); this._recognition.start(); } }; SpeechControl.prototype._disableRec = function () { window.sessionStorage.setItem('ARLY_DISABLE_REC', 'true'); this.stop(); }; SpeechControl.prototype.askForPermission = function () { return rxjs_1.from(navigator.mediaDevices.getUserMedia({ audio: true }).then(function (stream) { // stop it immediately, its just used to trigger the permission stream.getTracks().forEach(function (track) { track.stop(); }); })); }; SpeechControl.prototype.whenPermissionGranted = function () { if (!navigator.permissions) { console.warn('SPEECH CONTROL: PERMISSIONS API IS NOT AVAILABLE, USING getUserMedia HERE'); return this.askForPermission(); } var handleState = function (subscriber, status) { if (status.state == 'granted') { subscriber.next(); subscriber.complete(); } else if (status.state == 'prompt') { status.addEventListener('change', function (_a) { var target = _a.target; handleState(subscriber, target); }); } else { subscriber.error(); } }; return new rxjs_1.Observable(function (subscriber) { ; navigator.permissions .query({ name: 'microphone' }) .then(function (status) { return handleState(subscriber, status); }); }); }; SpeechControl.prototype.isEnabled = function () { // check if not disabled and speech _recognition available return (!window.sessionStorage.getItem('ARLY_DISABLE_REC') && (window.hasOwnProperty('SpeechRecognition') || window.hasOwnProperty('webkitSpeechRecognition'))); }; SpeechControl.prototype.setNotification = function (notification) { this.notification = notification; }; SpeechControl.prototype.on = function (term) { var _this = this; if (!this._observable) { this._observable = this.start().pipe(operators_1.finalize(function () { return (_this._observable = undefined); })); } return this._observable.pipe(operators_1.filter(function (event) { var item = event.results .item(event.results.length - 1)[0] .transcript.trim() .toLowerCase() .replace(/\s/g, ', '); return item.includes(term); })); }; SpeechControl.prototype.start = function (notificationOptions) { var _this = this; this._stopped = false; return new rxjs_1.Observable(function (subscriber) { if (_this.isEnabled()) { _this._record(subscriber); _this.whenPermissionGranted().subscribe(function () { if (!_this._notificationShown) { var notification = notification_1.append(notificationOptions || _this.notification); notification.then(function (nr) { return nr.disable.then(function () { _this._disableRec(); subscriber.error(SpeechControlErrors.Disabled); }); }); setTimeout(notification_1.remove, 3000); _this._notificationShown = true; } }); } else { subscriber.error(SpeechControlErrors.NoSpeechRecognition); } }).pipe(operators_1.debounceTime(500), operators_1.repeatWhen(function (complete) { return complete.pipe(operators_1.mergeMap(function () { // repeat because continouse does not work on all mobile devices if (_this._stopped) { return rxjs_1.empty(); } return rxjs_1.timer(500); })); }), operators_1.retryWhen(function (error) { return error.pipe(operators_1.mergeMap(function (error) { console.log(error); // retry if noting said if (error && error.error === 'no-speech') { return rxjs_1.timer(500); } return rxjs_1.throwError(error); })); })); }; SpeechControl.prototype.stop = function () { notification_1.remove(); this._stopped = true; if (this._recognition) { this._recognition.stop(); } }; return SpeechControl; }()); exports.SpeechControl = SpeechControl; //# sourceMappingURL=speech-control.js.map