refactor(frontend): rename project to s2s-frontend
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
import { useEffect } from "react";
|
||||
|
||||
import type { VoiceController } from "../realtime/controller";
|
||||
|
||||
interface Recognition {
|
||||
lang: string;
|
||||
continuous: boolean;
|
||||
interimResults: boolean;
|
||||
onresult: ((event: { resultIndex: number; results: ArrayLike<ArrayLike<{ transcript: string }>> }) => void) | null;
|
||||
onerror: ((event: { error: string }) => void) | null;
|
||||
onend: (() => void) | null;
|
||||
start: () => void;
|
||||
abort: () => void;
|
||||
}
|
||||
declare global {
|
||||
interface Window {
|
||||
SpeechRecognition?: new () => Recognition;
|
||||
webkitSpeechRecognition?: new () => Recognition;
|
||||
}
|
||||
}
|
||||
/** Optional browser wake word; never owns the microphone during a voice session. */
|
||||
export function useWakeWord(enabled: boolean, controller: VoiceController) {
|
||||
useEffect(() => {
|
||||
const Constructor = window.SpeechRecognition ?? window.webkitSpeechRecognition;
|
||||
if (!enabled || !Constructor) {
|
||||
return;
|
||||
}
|
||||
const recognition = new Constructor();
|
||||
let stopped = false;
|
||||
let timer: ReturnType<typeof setTimeout> | undefined;
|
||||
recognition.lang = "es-ES";
|
||||
recognition.continuous = true;
|
||||
recognition.interimResults = true;
|
||||
const start = () => {
|
||||
if (!stopped) {
|
||||
try {
|
||||
recognition.start();
|
||||
} catch {
|
||||
/* A browser may require a click first. */
|
||||
}
|
||||
}
|
||||
};
|
||||
recognition.onresult = (event) => {
|
||||
for (let index = event.resultIndex; index < event.results.length; index++) {
|
||||
const text =
|
||||
event.results[index]?.[0]?.transcript
|
||||
.toLowerCase()
|
||||
.normalize("NFD")
|
||||
.replace(/[\u0300-\u036f]/g, "") ?? "";
|
||||
if (/\b(?:hola|ola)\s+(?:vocero|bocero|bosero|vocerro)\b/.test(text)) {
|
||||
stopped = true;
|
||||
recognition.abort();
|
||||
void controller.start(false, undefined, "hola vocero");
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
recognition.onerror = (event) => {
|
||||
if (["not-allowed", "service-not-allowed", "audio-capture"].includes(event.error)) {
|
||||
stopped = true;
|
||||
}
|
||||
};
|
||||
recognition.onend = () => {
|
||||
if (!stopped) {
|
||||
timer = setTimeout(start, 1000);
|
||||
}
|
||||
};
|
||||
start();
|
||||
return () => {
|
||||
stopped = true;
|
||||
clearTimeout(timer);
|
||||
recognition.onresult = null;
|
||||
recognition.onerror = null;
|
||||
recognition.onend = null;
|
||||
recognition.abort();
|
||||
};
|
||||
}, [enabled, controller]);
|
||||
}
|
||||
Reference in New Issue
Block a user