我如何使用从 audioContext 创建的分析器来检测是否可以听到播放的声音?
How can i use an analyser created from an audioContext to detect if a playing sound is audible?
首先我会描述我的问题,我正在从随机歌曲创建一个自动播放列表,有些歌曲在歌曲结束时有 10-15 秒的静音,我想要实现的是从分析器检测歌曲何时静音 5 秒并据此采取行动。
到目前为止我得到了这个:
var context, analyser, source, audio;
context = new (window.AudioContext || window.webkitAudioContext)();
analyser = context.createAnalyser();
audio = new Audio();
source = context.createMediaElementSource(audio)
source.connect(analyser);
analyser.connect(context.destination);
var playNext = function() {
var pickedSong;
// chooses a song from an api with several
// thousands of songs and store it in pickedSong
audio.src = pickedSong;
audio.play();
}
audio.addEventListener('ended', playNext);
playNext();
我知道答案在分析器的某个地方,但我没有发现它返回的数据有任何一致性。
我可以这样做:
var frequencies = new Float32Array(analyser.frequencyBinCount);
analyser.getFloatFrequencyData(frequencies);
并且频率 var 将包含 2048 个键,每个键都有一个随机的(对我来说)数字(-48.11、-55、-67 等),这些数字是否意味着与感知声音相关的任何东西播放?,我如何检测它是否足够低以至于人们会认为没有播放。
对于检测我主要想要这样的东西:
var isInSilence = function(){
return !audible;
}
var tries = 0;
var checker = function() {
tries = isInSilence() ? tries + 1 : 0;
if(tries >= 5) playNext();
setTimeout(checker, 1000);
}
checker();
唯一缺少的部分是检测歌曲当前是否静音,如有任何帮助,我们将不胜感激。
编辑:
根据 william 的回答,我设法通过这种方式解决了它:
var context, compressor, gain, source, audio;
context = new (window.AudioContext || window.webkitAudioContext)();
compressor = context.createDynamicsCompressor();
gain = context.createGain();
audio = new Audio();
source = context.createMediaElementSource(audio)
// Connecting source directly
source.connect(context.destination);
// Connecting source the the compresor -> muted gain
source.connect(compressor);
compressor.connect(gain);
gain.connect(context.destination);
gain.gain.value = 0; // muting the gain
compressor.threshold.value = -100;
var playNext = function() {
var pickedSong;
// chooses a song from an api with several
// thousands of songs and store it in pickedSong
audio.src = pickedSong;
audio.play();
}
audio.addEventListener('ended', playNext);
playNext();
var isInSilence = function(){
return compressor.reduction.value >= -50;
}
var tries = 0;
var checker = function() {
tries = isInSilence() ? tries + 1 : 0;
if(tries >= 5) playNext();
setTimeout(checker, 1000);
}
checker();
这是一个可能的解决方案,使用不同的方法 - 压缩器节点。这是一个简短的描述,但应该足以让您填写用例的详细信息:
创建压缩器节点并将输入源连接到它。
然后将压缩器连接到增益节点并将增益节点静音(将其设置为零)。将增益节点连接到 audioContext.destination
获取您的输入源并将其连接到 audioContext.destination
。
设置压缩器 属性 值以检测信号(以便它触发降低值)。
将 compressor.reduction.value
包裹在 setInterval
或 requestAnimationFrame
中以检查更改。
编写此值更改(或不更改)时执行所需操作所需的逻辑。
供将来参考 - getFloatFrequencyValues 分析器 returns 的值是该特定信号的分贝 - 因此“0”将是假设的完整信号,“-96”远低于正常动态范围人类。
使用getByteFrequencyValues 可能更容易,pre-munges 取值为0-255; 0 是合理的本底噪声。如果您正在寻找真正的静音,只需在所有分析仪箱中寻找零 - 如果您正在寻找安静的信号,minDecibels 的默认 -100 可能太低,因此寻找一个较低的数字(10 或更少? 你必须试验)。或者更改 minDecibels - 请参阅规范。
首先我会描述我的问题,我正在从随机歌曲创建一个自动播放列表,有些歌曲在歌曲结束时有 10-15 秒的静音,我想要实现的是从分析器检测歌曲何时静音 5 秒并据此采取行动。
到目前为止我得到了这个:
var context, analyser, source, audio;
context = new (window.AudioContext || window.webkitAudioContext)();
analyser = context.createAnalyser();
audio = new Audio();
source = context.createMediaElementSource(audio)
source.connect(analyser);
analyser.connect(context.destination);
var playNext = function() {
var pickedSong;
// chooses a song from an api with several
// thousands of songs and store it in pickedSong
audio.src = pickedSong;
audio.play();
}
audio.addEventListener('ended', playNext);
playNext();
我知道答案在分析器的某个地方,但我没有发现它返回的数据有任何一致性。
我可以这样做:
var frequencies = new Float32Array(analyser.frequencyBinCount);
analyser.getFloatFrequencyData(frequencies);
并且频率 var 将包含 2048 个键,每个键都有一个随机的(对我来说)数字(-48.11、-55、-67 等),这些数字是否意味着与感知声音相关的任何东西播放?,我如何检测它是否足够低以至于人们会认为没有播放。
对于检测我主要想要这样的东西:
var isInSilence = function(){
return !audible;
}
var tries = 0;
var checker = function() {
tries = isInSilence() ? tries + 1 : 0;
if(tries >= 5) playNext();
setTimeout(checker, 1000);
}
checker();
唯一缺少的部分是检测歌曲当前是否静音,如有任何帮助,我们将不胜感激。
编辑:
根据 william 的回答,我设法通过这种方式解决了它:
var context, compressor, gain, source, audio;
context = new (window.AudioContext || window.webkitAudioContext)();
compressor = context.createDynamicsCompressor();
gain = context.createGain();
audio = new Audio();
source = context.createMediaElementSource(audio)
// Connecting source directly
source.connect(context.destination);
// Connecting source the the compresor -> muted gain
source.connect(compressor);
compressor.connect(gain);
gain.connect(context.destination);
gain.gain.value = 0; // muting the gain
compressor.threshold.value = -100;
var playNext = function() {
var pickedSong;
// chooses a song from an api with several
// thousands of songs and store it in pickedSong
audio.src = pickedSong;
audio.play();
}
audio.addEventListener('ended', playNext);
playNext();
var isInSilence = function(){
return compressor.reduction.value >= -50;
}
var tries = 0;
var checker = function() {
tries = isInSilence() ? tries + 1 : 0;
if(tries >= 5) playNext();
setTimeout(checker, 1000);
}
checker();
这是一个可能的解决方案,使用不同的方法 - 压缩器节点。这是一个简短的描述,但应该足以让您填写用例的详细信息:
创建压缩器节点并将输入源连接到它。
然后将压缩器连接到增益节点并将增益节点静音(将其设置为零)。将增益节点连接到 audioContext.destination
获取您的输入源并将其连接到 audioContext.destination
。
设置压缩器 属性 值以检测信号(以便它触发降低值)。
将 compressor.reduction.value
包裹在 setInterval
或 requestAnimationFrame
中以检查更改。
编写此值更改(或不更改)时执行所需操作所需的逻辑。
供将来参考 - getFloatFrequencyValues 分析器 returns 的值是该特定信号的分贝 - 因此“0”将是假设的完整信号,“-96”远低于正常动态范围人类。
使用getByteFrequencyValues 可能更容易,pre-munges 取值为0-255; 0 是合理的本底噪声。如果您正在寻找真正的静音,只需在所有分析仪箱中寻找零 - 如果您正在寻找安静的信号,minDecibels 的默认 -100 可能太低,因此寻找一个较低的数字(10 或更少? 你必须试验)。或者更改 minDecibels - 请参阅规范。