"Se um trabalhador quiser fazer bem o seu trabalho, ele deve primeiro afiar suas ferramentas." - Confúcio, "Os Analectos de Confúcio. Lu Linggong"
Primeira página > Programação > Entrada de áudio para texto via Google Speech to Text

Entrada de áudio para texto via Google Speech to Text

Publicado em 01/11/2024
Navegar:392

Audio to Text Input via Google Speech to Text

Neste artigo, examinaremos os seguintes tópicos

  1. navigator.mediaDevices.getUserMedia API do navegador
  2. API do Google Speech para texto

começaremos criando um gancho de reação que fará todas as coisas como startRecording, stopRecording, criação de Audio Blob, tratamento de erros, etc.

Há algumas outras coisas para cuidar antes de entrarmos na carne do anzol

    Decibel mínimo acima do qual consideraríamos um diálogo como entrada, por exemplo, -35db (apenas um número aleatório)
  1. Qual deve ser a duração da pausa que indicaria que o usuário interrompeu a entrada, por exemplo, 2.000 ms
const VOICE_MIN_DECIBELS = -35 const DELAY_BETWEEN_DIALOGUE = 2000
const VOICE_MIN_DECIBELS = -35
const DELAY_BETWEEN_DIALOGUE = 2000

Vamos nomear nosso gancho como useAudioInput.ts, estaríamos usando APIs do navegador como navigator.mediaDevices.getUserMedia, MediaRecorder e AudioContext. AudioContext nos ajudará a identificar se o áudio de entrada é superior ao decibel mínimo necessário para ser considerado como entrada, então começaríamos com as seguintes variáveis ​​e adereços


const defaultConfig = { áudio: verdadeiro }; tipo Carga = Blob; digite Configuração = { áudio: booleano; timeSlice?: número timeInMillisToStopRecording?: número onStop:() => vazio; onDataReceived: (carga útil: carga útil) => void }; export const useAudioInput = (config: Config = defaultConfig) => { const mediaChunks = useRef([]); const [isRecording, setIsRecording] = useState(false); const mediaRecorder = useRef(nulo); const [erro, setError] = useState(nulo); deixe requestId: número; deixe o temporizador: ReturnType; const criarBlob = () => { const [pedaço] = mediaChunks.atual; const blobProperty = { tipo: chunk.type }; retornar novo Blob (mediaChunks.current, blobProperty) } ... }
const VOICE_MIN_DECIBELS = -35
const DELAY_BETWEEN_DIALOGUE = 2000

No código acima, usaríamos mediaChunks como variável para armazenar o blob de entrada e mediaRecorder para ter uma instância do novo MediaRecorder que recebe o stream como entrada de navigator.mediaDevices.getUserMedia. A seguir, vamos cuidar dos casos em que getUserMedia não está disponível


... useEffect(() => { if(!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) { const notAvailable = new Error('Seu navegador não suporta entrada de áudio') setError(notAvailable) } },[]); ...
const VOICE_MIN_DECIBELS = -35
const DELAY_BETWEEN_DIALOGUE = 2000

começaremos a escrever a funcionalidade real do gancho, que consistirá em várias funções como setupMediaRecorder, setupAudioContext, onRecordingStart, onRecordingActive, startRecording, stopRecording etc.


const onRecordingStart = () => mediaChunks.current = []; const onRecordingActive = useCallback(({dados}: BlobEvent) => { se(dados) { mediaChunks.current.push(dados); config?.onDataReceived?.(createBlob()) } },[configuração]); const startTimer = () => { temporizador = setTimeout(() => { stopRecording(); },config.timeInMillisToStopRecording) }; const setupMediaRecorder = ({stream}:{stream: MediaStream}) => { mediaRecorder.current = novo MediaRecorder (fluxo) mediaRecorder.current.ondataavailable = onRecordingActive mediaRecorder.current.onstop=onRecordingStop mediaRecorder.current.onstart=onRecordingStart mediaRecorder.current.start(config.timeSlice) }; const setupAudioContext = ({stream}:{stream: MediaStream}) => { const audioContext = new AudioContext(); const audioStreamSource = audioContext.createMediaStreamSource(stream); const analisador = audioContext.createAnalyser(); analisador.minDecibels = VOICE_MIN_DECIBELS; audioStreamSource.connect(analisador); const bufferLength = analisador.frequencyBinCount; const domínioData = novo Uint8Array (bufferLength) retornar { domínioDados, comprimento do buffer, analisador } }; const startRecording=async()=>{ setIsRecording(true); aguarde navegador.mediaDevices .getUserMedia({ áudio: config.audio }) .então((fluxo) => { setupMediaRecorder({stream}); if(config.timeSlice) { const {domainData, analisador, bufferLength } = setupAudioContext({ stream }); startTimer() } }) .catch(e => { setError(e); setIsRecording(falso) }) }; const stopRecording = () => { mediaRecorder.current?.stop(); clearTimeout(temporizador); window.cancelAnimationFrame(requestId); setIsRecording(falso); onRecordingStop() }; const criarBlob = () => { const [pedaço] = mediaChunks.atual; const blobProperty = { tipo: chunk.type }; retornar novo Blob (mediaChunks.current, blobProperty) } const onRecordingStop = () => config?.onStop?.();
const VOICE_MIN_DECIBELS = -35
const DELAY_BETWEEN_DIALOGUE = 2000

com o código acima estamos quase terminando o gancho, a única coisa pendente é identificar se o usuário parou de falar ou não, usaríamos DELAY_BETWEEN_DIALOGUE como o tempo que esperaríamos, caso não haja entrada para 2 segundos, assumiremos que o usuário parou de falar e atingirá o endpoint de fala para texto.


... const detectarSom = ({ gravação, analisador, comprimento do buffer, domínioDados }: { gravação: booleano analisador: AnalyserNode comprimento do buffer: número dados de domínio: Uint8Array }) => { deixe lastDetectedTime = performance.now(); deixe anySoundDetected = falso; const cálculo = () => { if (!gravação) { retornar; } const currentTime = performance.now(); const timeBetweenTwoDialog = anySoundDetected === true && currentTime - lastDetectedTime > DELAY_BETWEEN_DIALOGUE; if (timeBetweenTwoDialog) { stopRecording(); retornar; } analisador.getByteFrequencyData(domainData); for (seja i = 0; i 0) { anySoundDetected = verdadeiro; lastDetectedTime = performance.now(); } } requestId = window.requestAnimationFrame(compute); }; calcular(); } ... const startRecording=async()=>{ ... detectarSom() ... }
const VOICE_MIN_DECIBELS = -35
const DELAY_BETWEEN_DIALOGUE = 2000

no código acima estamos usando requestAnimationFrame para detectar a entrada de áudio do usuário, com isso concluímos o gancho e agora podemos começar a usá-lo em vários lugares.

por exemplo


const onDataReceived = async (dados: BodyInit) => { const rawResponse = aguardar busca('https://backend-endpoint', { método: 'POST', corpo: dados }); resposta const = aguarda rawResponse.json(); setText(resposta) }; const { isRecording, startRecording, erro } = useAudioInput({ áudio: verdadeiro, timeInMillisToStopGravação: 2000, fatia de tempo: 400, onDataRecebido })
const VOICE_MIN_DECIBELS = -35
const DELAY_BETWEEN_DIALOGUE = 2000

A segunda parte é conectar um servidor de nó que possa se comunicar com o Google Speech para a API de texto. Anexei a documentação que mencionei ao criar o lado do nó.

https://codelabs.developers.google.com/codelabs/cloud-speech-text-node.

// servidor de nó de demonstração que se conecta com o Google Speech ao endpoint da API de texto const expresso = requer('expresso'); const cors = require('cors'); const discurso = require('@google-cloud/speech'); cliente const = novo discurso.SpeechClient(); função assíncrona convert(audioBlob) { solicitação constante = { configuração: { encoding: 'WEBM_OPUS', // Certifique-se de que corresponde ao formato do áudio que está sendo enviado sampleRateHertz: 48000, // Deve corresponder à taxa de amostragem da sua gravação código do idioma: 'en-US' }, áudio: { conteúdo: audioBlob } }; const [resposta] = aguardar client.recognize(request); transcrição const = resposta.resultados .map(resultado => resultado.alternativas[0].transcrição) .juntar('\n'); transcrição de retorno; } const app=express(); app.use(cors()) app.use(express.json()); app.post('/upload', express.raw({ tipo: '*/*' }), async (req, res) => { const audioBlob = req.body; resposta const = aguardar conversão (audioBlob); res.json(resposta); }); app.listen(4000,'0.0.0.0', () => { console.log('Exemplo de aplicativo escutando na porta 4000!'); });
const VOICE_MIN_DECIBELS = -35
const DELAY_BETWEEN_DIALOGUE = 2000

neste artigo, abordei o envio de conteúdo de áudio ou blob para o endpoint de texto do Google Speech, também podemos enviar um uri de blob em vez de conteúdo, a única alteração será a carga útil


// enviando url como parte do objeto de áudio para fala para API de texto ... áudio: {url: audioUrl} ou áudio: {content: audioBlob} ...
const VOICE_MIN_DECIBELS = -35
const DELAY_BETWEEN_DIALOGUE = 2000

O código relacionado ao artigo está presente no Github.

Declaração de lançamento Este artigo foi reproduzido em: https://dev.to/shubhadip/audio-to-text-input-via-google-speech-to-text-4ob0?1 Se houver alguma violação, entre em contato com [email protected] para excluí-lo
Tutorial mais recente Mais>

Isenção de responsabilidade: Todos os recursos fornecidos são parcialmente provenientes da Internet. Se houver qualquer violação de seus direitos autorais ou outros direitos e interesses, explique os motivos detalhados e forneça prova de direitos autorais ou direitos e interesses e envie-a para o e-mail: [email protected]. Nós cuidaremos disso para você o mais rápido possível.

Copyright© 2022 湘ICP备2022001581号-3