Хорошо, поэтому я пытаюсь определить интенсивность (в дБ) образцов аудиофайла, записанного браузером пользователя.
Мне удалось записать его и воспроизвести через элемент HTML. Но когда я пытаюсь использовать этот элемент в качестве источника и подключить его к AnalyserNode, AnalyserNode.getFloatFrequencyData всегда возвращает массив, полный -Infinity, getByteFrequencyData всегда возвращает нули, getByteTimeDomainData заполнен 128.
Вот мой код:
var audioCtx = new (window.AudioContext || window.webkitAudioContext)();
var source;
var analyser = audioCtx.createAnalyser();
var bufferLength = analyser.frequencyBinCount;
var data = new Float32Array(bufferLength);
mediaRecorder.onstop = function(e) {
var blob = new Blob(chunks, { 'type' : 'audio/ogg; codecs=opus' });
chunks = [];
var audioURL = window.URL.createObjectURL(blob);
// audio is an HTML audio element
audio.src = audioURL;
audio.addEventListener("canplaythrough", function() {
source = audioCtx.createMediaElementSource(audio);
source.connect(analyser);
analyser.connect(audioCtx.destination);
analyser.getFloatFrequencyData(data);
console.info(data);
});
}
Есть идеи, почему AnalyserNode ведет себя так, как будто источник пуст / отключен? Я также попытался поставить поток в качестве источника во время записи, с тем же результатом.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Если исходный файл из другого домена? Это приведет к ошибке createMediaElementSource.
Вам нужно получить аудиофайл и декодировать аудиобуфер. URL-адрес источника звука также должен находиться в том же домене или иметь правильные заголовки CORS (как упоминал Энтони).
Примечание. Замените <FILE-URI> на путь к вашему файлу в примере ниже.
var audioCtx = new (window.AudioContext || window.webkitAudioContext)();
var source;
var analyser = audioCtx.createAnalyser();
var button = document.querySelector('button');
var freqs;
var times;
button.addEventListener('click', (e) => {
fetch("<FILE-URI>", {
headers: new Headers({
"Content-Type" : "audio/mpeg"
})
}).then(function(response){
return response.arrayBuffer()
}).then((ab) => {
audioCtx.decodeAudioData(ab, (buffer) => {
source = audioCtx.createBufferSource();
source.connect(audioCtx.destination)
source.connect(analyser);
source.buffer = buffer;
source.start(0);
viewBufferData();
});
});
});
// Watch the changes in the audio buffer
function viewBufferData() {
setInterval(function(){
freqs = new Uint8Array(analyser.frequencyBinCount);
times = new Uint8Array(analyser.frequencyBinCount);
analyser.smoothingTimeConstant = 0.8;
analyser.fftSize = 2048;
analyser.getByteFrequencyData(freqs);
analyser.getByteTimeDomainData(times);
console.info(freqs)
console.info(times)
}, 1000)
}
этот код работал у меня на firefox, но не на chrome? Любые идеи
Не без дополнительной информации. Я предполагаю, что есть проблема совместимости с вашей версией Chrome? Если вы заглянете в консоль, то найдете хотя бы ключ к разгадке того, почему она не работает.
это действительно было!
Я столкнулся с той же проблемой, благодаря некоторым вашим фрагментам кода, я заставил ее работать со своей стороны (приведенный ниже код является машинописным и не будет работать в браузере на момент написания):
audioCtx.decodeAudioData(this.result as ArrayBuffer).then(function (buffer: AudioBuffer) {
soundSource = audioCtx.createBufferSource();
soundSource.buffer = buffer;
//soundSource.connect(audioCtx.destination); //I do not need to play the sound
soundSource.connect(analyser);
soundSource.start(0);
setInterval(() => {
calc(); //In here, I will get the analyzed data with analyser.getFloatFrequencyData
}, 300); //This can be changed to 0.
// The interval helps with making sure the buffer has the data
Некоторое объяснение (я все еще новичок, когда дело доходит до API веб-аудио, поэтому мое объяснение может быть неправильным или неполным):
Анализатор должен уметь анализировать определенную часть вашего звукового файла. В этом случае я создаю AudioBufferSoundNode, содержащий буфер, который я получил при декодировании аудиоданных. Я скармливаю буфер источнику, который в конечном итоге можно будет скопировать внутри Анализатора. Однако без обратного вызова интервала буфер никогда не кажется готовым, а проанализированные данные содержат -Inifinity (что, как я предполагаю, является отсутствием звука, так как ему нечего читать) в каждом индексе массива. Вот почему интервал есть. Он анализирует данные каждые 300 мс.
Надеюсь, это кому-то поможет!
Создается линией
var audioURL = window.URL.createObjectURL(blob);с данными из MediaRecorder.