|
|
|
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 |
|
} |
|
} |
|
} |
|
|
|
|