Estoy haciendo una herramienta de voz a texto. Estoy capturando audio en tiempo real (usando la API de audio web de Chrome) y lo envío a un servidor para convertir el audio en texto.
Me gustaría extraer fragmentos de todo el audio porque solo quiero enviar frases, evitando silencios. (porque la api que uso tiene un costo). El problema es que no sé cómo convertir todo el audio en partes.
Estaba usando MediaRecorder para capturar el audio
// recording this.recorder = new MediaRecorder(stream) this.recorder.ondataavailable = async (e) => { const buffer = await e.data.arrayBuffer() this.chunks.add(new Uint8Array(buffer)) } this.recorder.start(1000) Ahora tengo en this.chunks una matriz de búferes indexados por segundo.
Si trato de reproducir todo el archivo de audio pasando todo el búfer capturado, puede decodificarlo y reproducirlo correctamente:
// reproduce the whole audio: <- this works const combinedChunks = this.chunks.reduce((prev, chunk) => [...prev,...chunk], []) const arrChunks = new Uint8Array(combinedChunks) this.repAudioContext = new AudioContext() this.repAudioBuffer = await this.repAudioContext.decodeAudioData( arrChunks.buffer ) this.repSourceNode = this.repAudioContext.createBufferSource() this.repSourceNode.buffer = this.repAudioBuffer this.repSourceNode.connect(this.repAudioContext.destination) this.repSourceNode.start() Eso funciona ^, porque estoy usando todas las piezas. Pero como quiero extraer partes del audio, quiero poder seleccionar solo las partes del búfer que quiero reproducir. Y no puedo hacer eso. Si extraigo la primera pieza de audio, deja de funcionar y obtengo: decodeAudioData - Unable to decode audio data .
// reproduce a part of the audio captured: <- this won't work const combinedChunks = this.chunks.slice(1).reduce((prev, chunk) => [...prev,...chunk], []) // <- skipping first chunk const arrChunks = new Uint8Array(combinedChunks) this.repAudioContext = new AudioContext() this.repAudioBuffer = await this.repAudioContext.decodeAudioData( arrChunks.buffer ) this.repSourceNode = this.repAudioContext.createBufferSource() this.repSourceNode.buffer = this.repAudioBuffer this.repSourceNode.connect(this.repAudioContext.destination) this.repSourceNode.start()Entiendo que esto podría deberse a que en la primera parte hay encabezados u otros metadatos del audio capturado. Pero no puedo encontrar una manera de hacer esto.
¿Alguien puede darme algún consejo? ¿Hay una API diferente que debería usar? ¿Cuál es la forma adecuada de extraer una pieza de audio más pequeña de una más grande que pueda reproducir y guardar como archivo?
Encontré la respuesta a mi propia pregunta, estaba usando el enfoque incorrecto.
Lo que necesito usar para obtener las entradas de audio sin procesar y poder manipularlas es AudioWorkletProcessor.
Este video me ayudó a entender la teoría detrás:
https://www.youtube.com/watch?v=g1L4O1smMC0
Y este artículo me ayudó a entender cómo usarlo: https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API/Using_AudioWorklet