如何从mediaDevices.getUserMedia流中获取采样率



Firefox对音频媒体流的音频重采样能力有限。如果输入媒体流的采样率与AudioCotext的采样率不同,则它会抱怨:

DOMException: AudioContext.createMediaStreamSource: Connecting AudioNodes from AudioContexts with different sample-rate is currently not supported.

例如,如果我们得到这样的音频流:

navigator.mediaDevices.getUserMedia(constraints).then(stream => {
let context = new (window.AudioContext || window.webkitAudioContext)({sampleRate : 48000});  
let audioInput = this.context.createMediaStreamSource(stream);
});

如果音频上下文和音频子系统中硬件设备的设置不同,Firefox会抱怨采样率不匹配。

我找不到从流中的音轨中获得采样率的方法。我试过:

let tracks = stream.getAudioTracks();
let settings = tracks[0].getSettings();
let constraints = tracks[0].getConstraints();

但是这些对象中都没有流的sampleRate。

有没有其他方法可以查询音轨/流的采样率?

似乎可以将getUserMedia中的音频流连接到默认的AudioContext,而不受任何约束(不要指定采样率(。流连接后,您可以查看AudioContext.sampleRate,它会从getUserMedia((中告诉流的采样率。

我认为在Firefox中获得真正的sampleRate的唯一方法是使用MediaRecorder进行尽可能小的录制。默认情况下,Firefox会将MediaStream记录为'audio/ogg; codecs=opus'。这意味着它将以48kHz的采样率对所有音频进行编码,即使原始采样率不同。但是在Opus头中有一个字段存储原始采样率。幸运的是,这似乎在Firefox中得到了正确的填充。

const getSampleRateWithFallback = (mediaStream) => new Promise((resolve, reject) => {
try {
const { sampleRate } = mediaStream.getAudioTracks()[0].getSettings();
if (typeof sampleRate === 'number') {
resolve(sampleRate);
} else {
const mediaRecorder = new MediaRecorder(mediaStream, { mimeType: 'audio/ogg; codecs=opus' });
mediaRecorder.ondataavailable = ({ data }) => {
data.arrayBuffer().then(
(arrayBuffer) => {
const dataView = new DataView(arrayBuffer);
resolve(dataView.getInt32(40, true));
},
reject
);
};
mediaRecorder.start();
mediaRecorder.stop();
}
} catch (err) {
reject(err);
}
});

它应该在Firefox和Chrome中工作。它可以这样测试:

const audioContext = new AudioContext({ sampleRate: 32000 });
const mediaStreamAudioDestinationNode = new MediaStreamAudioDestinationNode(audioContext);
const oscillatorNode = new OscillatorNode(audioContext);
oscillatorNode.connect(mediaStreamAudioDestinationNode);
oscillatorNode.start();
getSampleRateWithFallback(mediaStreamAudioDestinationNode.stream)
.then((sampleRate) => console.log(sampleRate));

相关内容

  • 没有找到相关文章

最新更新