@sv-use/core
Version:
A collection of Svelte 5 utilities.
90 lines (89 loc) • 2.91 kB
JavaScript
import { whenever } from '../whenever/index.svelte.js';
import { isSupported } from '../__internal__/is.svelte.js';
import { noop, normalizeValue } from '../__internal__/utils.svelte.js';
import { defaultWindow } from '../__internal__/configurable.js';
/**
* Reactive controller interface for the recognition service.
* @param options Additional options to customize the behavior.
* @see https://svelte-librarian.github.io/sv-use/docs/core/create-speech-recognition
*/
export function createSpeechRecognition(options = {}) {
const { interimResults = true, continuous = true, maxAlternatives = 1, lang = 'en-US', onError = noop, onResult = noop, window = defaultWindow } = options;
let recognition;
let isListening = $state(false);
let isFinal = $state(false);
let result = $state('');
let error = $state(null);
const _lang = $derived(normalizeValue(lang));
const SpeechRecognition =
// eslint-disable-next-line @typescript-eslint/no-explicit-any
window && (window.SpeechRecognition || window.webkitSpeechRecognition);
const _isSupported = isSupported(() => SpeechRecognition);
if (_isSupported.current) {
recognition = new SpeechRecognition();
recognition.continuous = continuous;
recognition.interimResults = interimResults;
recognition.lang = _lang;
recognition.maxAlternatives = maxAlternatives;
recognition.onstart = () => {
isListening = true;
isFinal = false;
};
recognition.onresult = (event) => {
const currentResult = event.results[event.resultIndex];
const { transcript } = currentResult[0];
isFinal = currentResult.isFinal;
result = transcript;
error = null;
onResult(transcript, isFinal);
};
recognition.onerror = (event) => {
error = event;
onError(event);
};
recognition.onend = () => {
isListening = false;
};
whenever(() => !!_lang && !!recognition && !isListening, () => {
recognition.lang = _lang;
});
}
function start() {
if (!isListening) {
recognition?.start();
}
}
function stop() {
if (isListening) {
recognition?.stop();
}
}
return {
get isSupported() {
return _isSupported.current;
},
get isListening() {
return isListening;
},
get isFinal() {
return isFinal;
},
get recognition() {
return recognition;
},
get result() {
return result;
},
set result(v) {
result = v;
},
get error() {
return error;
},
set error(v) {
error = v;
},
start,
stop
};
}