prueba probar online microfono grabar camara javascript node.js web-audio-api google-cloud-speech audiocontext

javascript - probar - ¿Cómo puedo extraer el audio anterior(del micrófono) como un búfer cuando se detecta silencio(JS)?



prueba de camara (3)

Estoy usando la API de Google Cloud para voz a texto, con un back-end de NodeJS. La aplicación debe poder escuchar los comandos de voz y transmitirlos al back-end como un búfer. Para esto, necesito enviar el búfer del audio anterior cuando se detecta el silencio.

Cualquier ayuda sería apreciada. Incluyendo el código js abajo

if (!navigator.getUserMedia) navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia; if (navigator.getUserMedia) { navigator.getUserMedia({audio: true}, success, function (e) { alert(''Error capturing audio.''); }); } else alert(''getUserMedia not supported in this browser.''); var recording = false; window.startRecording = function () { recording = true; }; window.stopRecording = function () { recording = false; // window.Stream.end(); }; function success(e) { audioContext = window.AudioContext || window.webkitAudioContext; context = new audioContext(); // the sample rate is in context.sampleRate audioInput = context.createMediaStreamSource(e); var bufferSize = 4096; recorder = context.createScriptProcessor(bufferSize, 1, 1); recorder.onaudioprocess = function (e) { if (!recording) return; console.log(''recording''); var left = e.inputBuffer.getChannelData(0); console.log(convertoFloat32ToInt16(left)); }; audioInput.connect(recorder); recorder.connect(context.destination); }


El método más simple sería utilizar los .pause() y .resume() , .stop() de MediaRecorder() para permitir al usuario iniciar, pausar y detener la grabación del audio capturado utilizando navigator.mediaDevices.getUserMedia() y convertir Blob resultante en un ArrayBuffer , si eso es lo que la API espera que se POST en el servidor

<!DOCTYPE html> <html> <head> <title>User Media Recording</title> </head> <body> <input type="button" value="Start/resume recording audio" id="start"> <input type="button" value="Pause recording audio" id="pause"> <input type="button" value="Stop recording audio" id="stop"> <script> navigator.mediaDevices.getUserMedia({ audio: true }) .then(stream => { const recorder = new MediaRecorder(stream); recorder.ondataavailable = async(e) => { if (stream.active) { try { const blobURL = URL.createObjectURL(e.data); const request = await fetch(blobURL); const ab = await request.arrayBuffer(); // do stuff with `ArrayBuffer` of recorded audio console.log(blobURL, ab); // we do not need the `Blob URL`, we can revoke the object // URL.revokeObjectURL(blobURL); } catch (err) { throw err } } } recorder.onpause = e => { console.log("recorder " + recorder.state); recorder.requestData(); } stream.oninactive = () => { console.log("stream ended"); } document.getElementById("start") .onclick = () => { if (recorder.state === "inactive") { recorder.start(); } else { recorder.resume(); } console.log("recorder.state:", recorder.state); } document.getElementById("pause") .onclick = () => { if (recorder.state === "recording") { recorder.pause(); } console.log("recorder.state:", recorder.state); } document.getElementById("stop") .onclick = () => { if (recorder.state === "recording" || recorder.state === "paused") { recorder.stop(); } for (let track of stream.getTracks()) { track.stop(); } document.getElementById("start").onclick = null; document.getElementById("pause").onclick = null; console.log("recorder.state:", recorder.state , "stream.active", stream.active); } }) .catch(err => { console.error(err) }); </script> </body> </html>

plnkr https://plnkr.co/edit/7caWYMsvub90G6pwDdQp?p=preview


No estoy muy seguro de qué es exactamente lo que se pregunta en la pregunta, por lo que esta respuesta solo pretende dar una forma de detectar silencios en un AudioStream.

Para detectar el silencio en un AudioStream, puede usar un nodo AudioAnalyser , en el que llamará el método getByteFrequencyData a intervalos regulares, y verificar si hubo sonidos más altos que su nivel esperado durante un tiempo determinado.

Puede establecer el nivel de umbral directamente con la propiedad minDecibels de AnalyserNode.

function detectSilence( stream, onSoundEnd = _=>{}, onSoundStart = _=>{}, silence_delay = 500, min_decibels = -80 ) { const ctx = new AudioContext(); const analyser = ctx.createAnalyser(); const streamNode = ctx.createMediaStreamSource(stream); streamNode.connect(analyser); analyser.minDecibels = min_decibels; const data = new Uint8Array(analyser.frequencyBinCount); // will hold our data let silence_start = performance.now(); let triggered = false; // trigger only once per silence event function loop(time) { requestAnimationFrame(loop); // we''ll loop every 60th of a second to check analyser.getByteFrequencyData(data); // get current data if (data.some(v => v)) { // if there is data above the given db limit if(triggered){ triggered = false; onSoundStart(); } silence_start = time; // set it to now } if (!triggered && time - silence_start > silence_delay) { onSoundEnd(); triggered = true; } } loop(); } function onSilence() { console.log(''silence''); } function onSpeak() { console.log(''speaking''); } navigator.mediaDevices.getUserMedia({ audio: true }) .then(stream => { detectSilence(stream, onSilence, onSpeak); // do something else with the stream }) .catch(console.error);

Y como un violín ya que stackSnippets puede bloquear GUM.


Puede usar el evento de result SpeechRecognition para determinar cuándo una palabra o frase ha sido reconocida, por ejemplo, ls , cd , pwd u otros comandos, pasar el .transcript de SpeechRecognitionAlternative to SpeechRecognitionAlternative speechSynthesis.speak() donde se encuentra un evento adjunto de start y end de SpeechSynthesisUtterance llame a .start() o .resume() en el objeto MediaRecorder donde se pasa MediaStream ; convierta el evento Blob at dataavailable a un ArrayBuffer usando FileReader o Response.arrayBuffer() .

Alternativamente, podríamos utilizar audiostart o soundstart con audioend o soundend eventos de SpeechRecognition para grabar la voz real de los usuarios, aunque es posible que los extremos no se activen de forma consistente en relación con el inicio y el fin del audio capturado por un micrófono estándar del sistema.

<!DOCTYPE html> <html> <head> <title>Speech Recognition Recording</title> </head> <body> <input type="button" value="Stop speech command recognition" id="stop"> <script> navigator.mediaDevices.getUserMedia({ audio: true }) .then(stream => { const recorder = new MediaRecorder(stream); const recognition = new webkitSpeechRecognition(); const synthesis = new SpeechSynthesisUtterance(); const handleResult = e => { recognition.onresult = null; console.log(e.results); const result = e.results[e.results.length - 1]; if (result.isFinal) { const [{transcript}] = result; console.log(transcript); synthesis.text = transcript; window.speechSynthesis.speak(synthesis); } } synthesis.onstart = () => { if (recorder.state === "inactive") { recorder.start() } else { if (recorder.state === "paused") { recorder.resume(); } } } synthesis.onend = () => { recorder.pause(); recorder.requestData(); } recorder.ondataavailable = async(e) => { if (stream.active) { try { const blobURL = URL.createObjectURL(e.data); const request = await fetch(blobURL); const ab = await request.arrayBuffer(); console.log(blobURL, ab); recognition.onresult = handleResult; // URL.revokeObjectURL(blobURL); } catch (err) { throw err } } } recorder.onpause = e => { console.log("recorder " + recorder.state); } recognition.continuous = true; recognition.interimResults = false; recognition.maxAlternatives = 1; recognition.start(); recognition.onend = e => { console.log("recognition ended, stream.active", stream.active); if (stream.active) { console.log(e); // the service disconnects after a period of time recognition.start(); } } recognition.onresult = handleResult; stream.oninactive = () => { console.log("stream ended"); } document.getElementById("stop") .onclick = () => { console.log("stream.active:", stream.active); if (stream && stream.active && recognition) { recognition.abort(); recorder.stop(); for (let track of stream.getTracks()) { track.stop(); } console.log("stream.active:", stream.active); } } }) .catch(err => { console.error(err) }); </script> </body> </html>

plnkr https://plnkr.co/edit/4DVEg6mhFRR94M5gdaIp?p=preview