createSpeechRecognizer / isSpeechRecognitionSupported
Um invólucro em volta do SpeechRecognition da Web Speech API, a contraparte do AudioRecorder, que captura bytes de áudio; este aqui pede à plataforma que transforme a fala em texto.
Vale a pena embrulhar a API nativa uma vez em vez de mexer nela direto: no WebKit ela ainda leva prefixo (webkitSpeechRecognition), não aparece no lib.dom.d.ts e relata coisas que nem são acontecimentos (uma pausa em silêncio, um stop() que você mesmo chamou) pelo mesmo canal de erros de um microfone negado.
Uso
import { createSpeechRecognizer } from 'ranuts/utils';
const mic = createSpeechRecognizer({
lang: () => currentLocale(), // relido a cada captura, não uma vez só
onResult: (text, isFinal) => {
input.value = text;
},
onError: (e) => {
if (e.kind === 'denied') toast('O acesso ao microfone foi negado');
},
onStart: () => button.classList.add('recording'),
onEnd: () => button.classList.remove('recording'),
});
if (!mic.supported) button.style.display = 'none'; // esconder o botão do microfone logo de cara
button.addEventListener('click', () => mic.toggle());API
isSpeechRecognitionSupported()
Devolve boolean. A conferência acontece na chamada, não fica guardada no carregamento do módulo; então dá para importar este módulo durante a renderização no servidor e fazer a conferência quando a página hidratar.
createSpeechRecognizer(options?)
Monta um SpeechRecognizer reaproveitável. O start() cria toda vez uma instância nativa nova, então qualquer opção passada como função (lang, em especial) é relida no início de cada captura, em vez de congelar no momento da criação.
Parâmetros (SpeechRecognizerOptions)
| Opção | Descrição | Tipo | Padrão |
|---|---|---|---|
lang | Etiqueta BCP 47 ('en-US', 'zh-CN'), ou uma função lida no início de cada captura | string | (() => string) | '' |
continuous | Continuar ouvindo através das pausas em vez de parar na primeira | boolean | true |
interimResults | Emitir resultados parciais enquanto a pessoa fala | boolean | true |
onResult | Chamado com a transcrição de toda a captura até ali e com se ela é definitiva | (transcript: string, isFinal: boolean) => void | - |
onError | Chamado com um erro já classificado | (error: SpeechError) => void | - |
onStart | Dispara quando uma captura começa | () => void | - |
onEnd | Dispara uma vez por captura, tenha ela acabado como for (parada, vencida ou com erro) | () => void | - |
SpeechRecognizer
| Membro | Descrição | Tipo |
|---|---|---|
supported | false quando a plataforma não tem reconhecimento de fala; aí nenhum método faz nada | boolean (getter) |
active | Se há uma captura em andamento | boolean (getter) |
start() | Começa uma captura. É ignorado se já houver uma em andamento | () => void |
stop() | Encerra a captura atual; o que já foi reconhecido fica, e em seguida vem o onEnd | () => void |
abort() | Encerra a captura atual e descarta os resultados pendentes | () => void |
toggle() | Começa se estiver parado e para se estiver em andamento: justo o que um único botão de microfone pede | () => void |
SpeechError
| Campo | Descrição | Tipo |
|---|---|---|
kind | 'denied' (microfone negado, vale mostrar), 'noSpeech' / 'aborted' (rotina, em geral não vale a pena mostrar), 'failed' (todo o resto) | SpeechErrorKind |
detail | A string error crua vinda do evento da plataforma | string |
Notas
- Não existe em todo lugar. O Firefox não implementa
SpeechRecognitionde jeito nenhum; confira semprerecognizer.supported(ouisSpeechRecognitionSupported()) antes de oferecer um microfone, em vez de supor que o construtor existe. supportedeactivesão getters, reavaliados a cada acesso, e não valores tomados uma vez na criação. Isso importa secreateSpeechRecognizer()rodar antes de existiremwindowou o construtor com prefixo do fabricante (renderização no servidor, uma chamada logo no escopo do módulo, antes da hidratação): o reconhecedor pega a API de verdade assim que ela aparece, em vez de ficar preso para sempre dizendosupported === false.- A transcrição do
onResulté acumulada, não incremental: é o texto inteiro da captura até ali, revisado conforme os resultados provisórios firmam. Não concatene você mesmo. - Instanciar o reconhecedor nativo ou chamar o
start()dele pode lançar de forma síncrona (por uma restrição da Permissions-Policy, ou peloInvalidStateErrordo Chrome quando já há uma captura em andamento); ocreateSpeechRecognizercaptura isso e avisa poronErroreonEndem vez de deixar escapar.