| | |
| | const SpeechRecognitionPolyfill: typeof webkitSpeechRecognition = typeof window !== 'undefined' ? ( |
| | |
| | window.SpeechRecognition || |
| | window.webkitSpeechRecognition || |
| | |
| | window.mozSpeechRecognition || |
| | |
| | window.msSpeechRecognition || |
| | |
| | window.oSpeechRecognition |
| | ) as typeof webkitSpeechRecognition : undefined |
| |
|
| | type subscriber = (msg: string, command?: string) => void |
| |
|
| | export class SR { |
| | recognition?: SpeechRecognition |
| | onchange?: subscriber |
| | transcript: boolean = false |
| | listening: boolean = false |
| | private commandsRe?: RegExp |
| | constructor(commands: string[]) { |
| | this.recognition = SpeechRecognitionPolyfill ? new SpeechRecognitionPolyfill() : undefined |
| | if (!this.recognition) { |
| | return |
| | } |
| | this.configuration('zh-CN') |
| | if (commands.length) { |
| | this.commandsRe = new RegExp(`^(${commands.join('|')})。?$`) |
| | } |
| | this.recognition.onresult = this.speechRecognition |
| | this.recognition.onerror = (err) => { |
| | console.log('err', err.error) |
| | this.stop() |
| | } |
| | this.recognition.onend = () => { |
| | if (this.recognition && this.listening) { |
| | this.recognition.start() |
| | } |
| | } |
| | } |
| |
|
| | speechRecognition = (event: SpeechRecognitionEvent) => { |
| | if (!this.listening) return |
| | for (var i = event.resultIndex; i < event.results.length; i++) { |
| | let result = event.results[i] |
| | if (result.isFinal) { |
| | var alt = result[0] |
| | const text = alt.transcript.trim() |
| | if (this.commandsRe && this.commandsRe.test(text)) { |
| | return this.onchange?.('', RegExp.$1) |
| | } |
| | if (!this.transcript) return |
| | this.onchange?.(text) |
| | } |
| | } |
| | } |
| |
|
| | private configuration = async (lang: string = 'zh-CN') => { |
| | return new Promise((resolve) => { |
| | if (this.recognition) { |
| | this.recognition.continuous = true |
| | this.recognition.lang = lang |
| | this.recognition.onstart = resolve |
| | } |
| | }) |
| | } |
| |
|
| | start = async () => { |
| | if (this.recognition && !this.listening) { |
| | await this.recognition.start() |
| | this.transcript = true |
| | this.listening = true |
| | } |
| | } |
| |
|
| | stop = () => { |
| | if (this.recognition) { |
| | this.recognition.stop() |
| | this.transcript = false |
| | this.listening = false |
| | } |
| | } |
| |
|
| |
|
| | pause = () => { |
| | if (this.recognition) { |
| | this.transcript = false |
| | } |
| | } |
| |
|
| | resume = () => { |
| | if (this.recognition) { |
| | this.transcript = true |
| | } |
| | } |
| |
|
| | abort = () => { |
| | if (this.recognition && this.transcript) { |
| | this.recognition.abort() |
| | this.transcript = false |
| | this.listening = false |
| | } |
| | } |
| | } |
| |
|
| |
|