Voice Button
Ditado para um compositor de texto, sobre a API Web Speech.
Use quando quiser a fala como mais uma forma de preencher um campo de texto, não como substituta. Digitar precisa continuar disponível: um caminho só por voz exclui quem tem uma diferença de fala, quem está numa sala barulhenta e quem usa um navegador sem reconhecimento algum.
Um botão de microfone, e nada além. Ele cuida da captura e informa o que ouviu; para onde esse texto vai é decisão de quem o usa, porque um componente que também escrevesse num campo teria de saber em qual, se acrescenta ou substitui, e o que fazer com o cursor: três respostas que mudam a cada aplicativo.
Início rápido
<r-voice-button label="Iniciar ditado" active-label="Parar ditado"></r-voice-button>const mic = document.createElement('r-voice-button');
mic.label = 'Iniciar ditado';
mic.activeLabel = 'Parar ditado';
const input = document.querySelector('textarea');
let base = '';
mic.addEventListener('voicestart', () => {
// Um espaço entre o que foi digitado e o que foi dito, a menos que já exista um.
base = input.value === '' || /\s$/.test(input.value) ? input.value : `${input.value} `;
});
mic.addEventListener('voiceresult', (event) => {
input.value = base + event.detail.transcript;
});
composer.append(mic);As decisões por trás disso
Ele informa a captura inteira, não o fragmento mais novo
Resultados provisórios são revisados conforme o reconhecimento avança: "你好" vira "你好世界",
e não chega um segundo evento carregando "世界". Quem acrescentasse cada evento terminaria com
你好你好世界. Lembre o texto que já estava no campo e concatene uma única vez.
Ele não envia
O reconhecimento erra com frequência suficiente para que confirmar em nome de quem fala tire dela a revisão de que precisa. Isto preenche a caixa e para por aí. Enviar continua sendo um ato deliberado.
Ele se esconde onde não existe reconhecimento
O Firefox não traz reconhecimento de fala, nem qualquer navegador em que a API esteja ausente.
Quando o reconhecimento não é suportado, o elemento se esconde com hidden em vez de se
desabilitar com disabled: disabled dá a entender que o recurso existe mas está temporariamente
indisponível, enquanto remover o botão é exato quando o recurso não existe nesta plataforma.
Mostrar um botão que nunca vai funcionar convidaria a um toque que não faz nada, e depois exigiria
uma explicação.
Só dois dos quatro erros valem a pena mostrar
| Tipo | O que é | Mostrar? |
|---|---|---|
denied |
o microfone foi recusado | sim (dá para agir) |
failed |
qualquer outra coisa deu errado | sim |
noSpeech |
uma pausa em silêncio | não |
aborted |
uma parada por código | não |
Os dois últimos chegam pelo mesmo canal de uma falha real e não são uma. Trazê-los à tona mostraria um erro depois de toda captura comum, não só das falhas de verdade.
Acessibilidade
O nome acessível muda com o estado, não só o ícone, e o aria-pressed carrega a alternância: um
leitor de tela anuncia "Parar ditado, pressionado", não um ícone. Escape descarta uma captura em
vez de confirmá-la, que é o que quer quem percebe no meio da frase que falou a coisa errada.
O estado de escuta é transmitido por borda, preenchimento e um anel, então não depende só da cor. O
anel é o único movimento e é decoração; prefers-reduced-motion o remove sem perder informação.
O idioma segue a página
lang é lido a cada captura e assume por padrão o do documento, então um aplicativo que troca de
idioma no meio da sessão dita no idioma que está exibindo.
Referência da API
Propriedades
| Propriedade | Tipo | Padrão | Descrição |
|---|---|---|---|
lang |
string |
o do documento | Etiqueta BCP 47 do idioma falado. Lida a cada captura. |
continuous |
boolean |
true |
Continua ouvindo através das pausas em vez de parar na primeira. |
disabled |
boolean |
false |
Desabilita o botão: start() é ignorado e o botão interno fica desabilitado. Não interrompe uma captura em andamento. |
label |
string |
'Start voice input' |
Nome acessível enquanto ocioso. |
activeLabel |
string |
'Stop voice input' |
Nome acessível enquanto ouve. |
listening |
boolean |
false |
Somente leitura, refletido: estilize com :host([listening]). |
supported |
boolean |
— | Somente leitura. Se esta plataforma consegue reconhecer fala. |
sheet |
string |
'' |
CSS injetado no shadow DOM do elemento. |
Métodos
start() · stop() (mantém o que foi reconhecido) · abort() (descarta) · toggle().
O toggle() lê o estado do próprio reconhecedor, e não o atributo refletido: uma captura que tenha
começado sem informar deixaria os dois em desacordo, e a próxima ativação tentaria abrir uma segunda
captura, seria recusada e não faria nada.
Eventos
| Evento | Detail | Disparado quando |
|---|---|---|
voicestart |
— | uma captura começa |
voiceresult |
{ transcript, isFinal } |
chega texto ou ele é revisado |
voiceerror |
{ kind, detail } |
a plataforma informa um problema |
voiceend |
— | a captura termina, seja qual for o motivo |
Partes
button, icon.
Estilos
O <r-voice-button> expõe 20 propriedades personalizadas de CSS próprias, além dos tokens
semânticos que lê do tema. Defina uma em qualquer lugar de onde ela seja herdada: :root, um
contêiner ou o próprio elemento:
r-voice-button {
--ran-voice-background: var(--ran-color-bg-subtle);
}Partes: button · hint · icon
A lista completa está em tokens de estilo; qual token escolher é assunto do design system.
Veja também
createSpeechRecognizer: o reconhecedor que isto envolve- Conversation: a transcrição em que uma mensagem ditada aterrissa