#web-audio-api
#web-audio-api
Вопрос:
Я хотел бы получить непрерывный поток сэмплов в JavaScript из audio API. Единственный способ, который я нашел для получения сэмплов, — это объект MediaRecorder в JavaScript Audio API.
Я настроил свой рекордер следующим образом:
var options = {
mimeType: "audio/webm;codec=raw",
}
this.mediaRecorder = new MediaRecorder(stream, options);
this.mediaRecorder.ondataavailable = function (e) {
this.decodeChunk(e.data);
}.bind(this);
this.mediaRecorder.start(/*timeslice=*/ 100 /*ms*/);
Это дает мне обратный вызов 10 раз в секунду с новыми данными. Пока все хорошо.
Данные закодированы, поэтому я использую audioCtx.decodeAudioData для их обработки:
let fileReader = new FileReader();
fileReader.onloadend = () => {
let encodedData = fileReader.resu<
// console.log("Encoded length: " encodedData.byteLength);
this.audioCtx.decodeAudioData(encodedData,
(decodedSamples) => {
let newSamples = decodedSamples.getChannelData(0)
.slice(this.firstChunkSize, decodedSamples.length);
// The callback which handles the decodedSamples goes here. All good.
if (this.firstChunkSize == 0) {
this.firstChunkSize = decodedSamples.length;
}
});
};
Все это тоже работает нормально.
Настройка данных для программы чтения файлов — вот где это становится странным:
let blob;
if (!this.firstChunk) {
this.firstChunk = chunk;
blob = new Blob([chunk], { 'type': chunk.type });
} else {
blob = new Blob([this.firstChunk, chunk], { 'type': chunk.type });
}
fileReader.readAsArrayBuffer(blob);
Первый фрагмент работает просто отлично, но второй и последующие фрагменты не декодируются, если я не объединю их с первым фрагментом. Я предполагаю, что здесь происходит то, что первый фрагмент имеет заголовок, который требуется для декодирования данных. Я удаляю сэмплы, декодированные из первого фрагмента, после их декодирования во второй раз. Смотрите this.firstChunkSize
выше.
Все это выполняется без ошибок, но звук, который я получаю обратно, имеет эффект, подобный вибрато, на частоте 10 Гц. Несколько гипотез:
-
У меня есть какая-то простая ошибка в моей логике «firstChunkSize» и «splice»
-
Первый фрагмент имеет некоторый заголовок, из-за которого оставшиеся данные интерпретируются странным образом.
-
При создании источника звука происходит какое-то странное взаимодействие с какой-либо опцией (шумоподавление?)
Комментарии:
1. Я обнаружил подсказку: это утверждение выполняется успешно после создания MediaRecorder, но не выполняется в ondataavailable обратном вызове: console.assert(this.MediaRecorder.mimeType == «audio / webm;codec= raw»). Кодек, похоже, меняется на «opus», но я не знаю почему. Я использую Chrome v86.
2. То же самое происходит, когда я пытаюсь использовать audio/webm;codecs=pcm, который является допустимым типом для: MediaRecorder.isTypeSupported(‘audio / webm;codecs=pcm’)
Ответ №1:
Вы хотите codecs=
, а не codec=
.
var options = {
mimeType: "audio/webm;codecs=pcm",
}
Хотя MediaRecorder.isSupported
вернет true с codec=
ним только потому, что этот параметр игнорируется. Например:
MediaRecorder.isTypeSupported("audio/webm;codec=pcm")
true
MediaRecorder.isTypeSupported("audio/webm;codecs=pcm")
true
MediaRecorder.isTypeSupported("audio/webm;codecs=asdfasd")
false
MediaRecorder.isTypeSupported("audio/webm;codec=asdfasd")
true
Имя мусорного кодека asdfasd
«поддерживается», если вы укажете codec
вместо codecs
.