当检测到静音(JS)时,如何将前一个音频(来自麦克风)提取为缓冲区?

时间:2017-10-03 11:18:10

标签: javascript node.js web-audio-api google-cloud-speech audiocontext

我正在使用带有NodeJS后端的Google Cloud API for Speech-to-text。 应用程序需要能够侦听语音命令,并将它们作为缓冲区传输到后端。为此,我需要在检测到静音时发送前一个音频的缓冲区。

任何帮助将不胜感激。包括下面的js代码

 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);
}

3 个答案:

答案 0 :(得分:16)

我不太确定问题的确切内容,所以这个答案只是为了找到一种方法来检测AudioStream中的静音。

要检测AudioStream中的静音,您可以使用AudioAnalyser节点,在该节点上定期调用getByteFrequencyData方法,并检查是否有高于预期水平的声音给定的时间。

您可以直接使用AnalyserNode的minDecibels属性设置阈值级别。



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);




as a fiddle因为stackSnippets可能会阻止gUM。

答案 1 :(得分:2)

您可以使用SpeechRecognition result事件来确定何时识别出某个字词或词组,例如lscdpwd或其他命令,将.transcript的{​​{1}}传递给SpeechRecognitionAlternative speechSynthesis.speak()start end来自SpeechSynthesisUtterance的{​​{1}}或{.start().resume()传递MediaRecorder的对象{1}};使用MediaStreamBlobdataavailable事件ArrayBuffer转换为FileReader

我们也可以Response.arrayBuffer()audiostart使用soundstartaudioend soundend事件来记录用户的实际语音,但结果可能不会与仅由标准系统麦克风捕获的音频的实际开始和结束相关地持续发射。

SpeechRecognition

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

答案 2 :(得分:2)

最简单的方法是使用.pause()的{​​{1}}和.resume().stop()方法,以允许用户使用{{开始,暂停和停止录制音频1}}并将生成的MediaRecorder()转换为navigator.mediaDevices.getUserMedia(),如果这是api期望Blob编辑到服务器

ArrayBuffer

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