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));