我正在通过网站录制和发送音频。为此,我使用 MediaRecorder API。
在桌面或 Android 设备上使用该网站时没有任何问题,并且根据 MediaRecorder 文档,自 2020 年 9 月发布以来,也应该支持 iOS 14。
MediaRecorder 实例化如下:
navigator.mediaDevices.getUserMedia({ audio: true, video: false })
.then((stream) => {
// Some validation and other processing. Omitted for brevity.
const mediaRecorder = new MediaRecorder(stream, { mimeType: 'audio/webm' });
// Using the mediaRecorder. Omitted for brevity.
});
在装有 iOS 14.6 的 iPhone 12 上执行此操作时,我从该实例化行收到以下错误:
NotSupportedError: mimeType is not supported
尝试其他格式时出现相同的错误(这些是我发现并尝试过的格式):
audio/webm
(如上例所示)video/webm
audio/ogg
(桌面上也有错误)audio/ogg; codecs=opus
(桌面上也有错误)MediaRecorder 是否有任何 mimeType 可以让我在 iOS 设备上使用音频?
我是否得到了其他完全错误的东西?
我的首选解决方案是这样的:
if (MediaRecorder.isTypeSupported('video/webm; codecs=vp9')) {
var options = {mimeType: 'video/webm; codecs=vp9'};
} else if (MediaRecorder.isTypeSupported('video/webm')) {
var options = {mimeType: 'video/webm'};
} else if (MediaRecorder.isTypeSupported('video/mp4')) {
var options = {mimeType: 'video/mp4', videoBitsPerSecond : 100000};
} else {
console.error("no suitable mimetype found for this device");
}
const mediaRecorder = new MediaRecorder(stream, options);
IOS仅允许mp4,因此运行此代码后您将自动获得该选项。
我相信这可能是比 try catch 更好的方法。
事实证明
video/mp4
适用于 iOS。它也可以仅用于音频,即使它说的是视频。
由于其他浏览器不支持
video/mp4
,因此可以使用带有 video/mp4
的 try/catch 作为后备,这会产生以下解决方案:
let mediaRecorder;
try {
mediaRecorder = new MediaRecorder(stream, { mimeType: 'audio/webm' });
}
catch (err1) {
try {
// Fallback for iOS
mediaRecorder = new MediaRecorder(stream, { mimeType: 'video/mp4' });
}
catch (err2) {
// If fallback doesn't work either. Log / process errors.
console.error({err1});
console.error({err2})
}
}
可以通过以下方式使代码更清晰、更明确:
NotSupportedError
但目前它可以工作,这对于个人项目来说已经足够好了。
使用可变列表长度重试的更紧凑答案
const mimeTypes = ["audio/webm", "video/mp4"];
const genericName = async (mimeIndex = 0) => {
try {
//Set the mimeType to the first item in the mimeTypes array
const mimeType = mimeTypes[mimeIndex];
MediaRecorder.isTypeSupported(mimeType);
//create new Media recorder instance using the stream
const media: MediaRecorder = new MediaRecorder(stream, { mimeType });
} catch (err: any) {
console.log("Error recording", err.message);
// Retry with the next mimeType if the first mimeType fails
const retries = mimeTypes.length;
if (mimeIndex < retries) {
startRecording(mimeIndex + 1);
}
}
};