当检测到静音(JS)时,如何将前一个音频(来自麦克风)提取为缓冲区? [英] How can I extract the preceding audio (from microphone) as a buffer when silence is detected (JS)?
问题描述
我正在使用带有NodeJS后端的Google Cloud API for Speech-to-text。
应用程序需要能够侦听语音命令,并将它们作为缓冲区传输到后端。为此,我需要在检测到静音时发送前一音频的缓冲区。
I'm using the Google Cloud API for Speech-to-text, with a NodeJS back-end. The app needs to be able to listen for voice commands, and transmit them to the back-end as a buffer. For this, I need to send the buffer of the preceding audio when silence is detected.
任何帮助都将不胜感激。包括下面的js代码
Any help would be appreciated. Including the js code below
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);
}
推荐答案
我不太确定至于究竟在问题中提出了什么,所以这个答案只是为了找到一种方法来检测AudioStream中的静音。
I'm not too sure as to what exactly is being asked in the question, so this answer is only intended to give a way to detect silences in an AudioStream.
要检测AudioStream中的静音,您可以使用 AudioAnalyser 节点,您将定期调用 getByteFrequencyData
方法,并检查在给定时间内是否有高于预期水平的声音。
To detect silence in an AudioStream, you can use an AudioAnalyser node, on which you will call the getByteFrequencyData
method at regular intervals, and check whether there were sounds higher than than your expected level for a given time.
您可以直接使用AnalyserNode的 minDecibels
属性设置阈值级别。
You can set the threshold level directly with the minDecibels
property of the 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);
作为小提琴因为stackSnippets可能会阻止gUM。
And as a fiddle since stackSnippets may block gUM.
这篇关于当检测到静音(JS)时,如何将前一个音频(来自麦克风)提取为缓冲区?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!