Pitch: o mesmo limiar de silêncio do micro zera o áudio da aba

Estou construindo o LiveSuggest, um assistente que fica na tela durante a reunião. Nenhum bot entra na chamada. O áudio sai do navegador em pedaços PCM16, 16 kHz, por WebSocket. O STT cobra o que realmente sai.

No micro, um gate de RMS no thread principal segura o silêncio antes do socket. O limiar é clamp(piso * 1.8, 0.0015, 0.02). O piso é uma média que só se move em pedaço já marcado como silêncio. 0.0015 deixa uma sala quieta falar baixo. 0.02 segura uma sala barulhenta para a fala normal não cair fora.

O primeiro pedaço audível grava o piso, antes de classificar. Sem isso o piso fica 0, o gate abre em 0.0015, a sala cruza, o estado entra em fala e a média nunca mais roda. O gate trava aberto até o fim da sessão.

if (this.noiseFloor === 0 && rms > 0) { this.noiseFloor = rms;}

A fala começa atrasada: as primeiras sílabas já estão em pedaços que pareciam silêncio. Um anel de 5 pedaços, cerca de meio segundo, sai junto quando o estado passa para fala. No meio da frase o RMS cai numa respiração. O gate continua aberto por 20 pedaços depois da fala, cerca de 2 segundos. O pedaço que fecha essa espera não vai para o socket. Ele atualiza o piso.

Áudio de aba e loopback do sistema chegam em nível de linha. O mesmo corte marca o sinal inteiro como silêncio. A transcrição para. Por isso o gate só existe na captura de micro. Assim que entra um fluxo de sistema, inclusive micro misturado com sistema, o gate é pulado. hasSystemAudio é só systemStream !== null. Todo pedaço segue, o flag de fala fica ligado, e o ruído vai para o STT. Sem segundo limiar e sem rodar esse VAD na aba.

if (disableVAD) { emit(); return;}

O texto mais longo, em inglês: Building Real-Time AI Suggestions Without a Meeting Bot.

Source

1 view·1 share