我正在使用 React Js 构建一个应用程序,它可以录制用户的音频,将文件或 blob 上传到云存储,并从文件 URL 播放录制的音频。
问题是,当从 Chrome 录制音频时,它只能在 Chrome 上播放,而不能在 Safari 中播放。 另一方面,如果音频是从 Safari 录制的,则它在两个浏览器上都可以正常播放。
已测试
这是实现。
录音部分:
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
const recorder = new MediaRecorder(stream);
recorder.addEventListener('dataavailable', ({ data }) => {
const audioBlob = new Blob([data], { type: 'audio/mpeg' });
// or new File([audioBlob], 'name.mp3', { type: 'audio/mpeg' });
// upload blob or file to server
});
// on start
recorder.start();
// on stop
recorder.stop();
recorder.stream.getTracks().forEach((i) => i.stop());
回放部分;
const audioInstanceRef = useRef<HTMLAudioElement | null>(null);
useEffect(() => {
audioInstanceRef.current = new Audio();
}, []);
const play = (url: string) => {
if (!audioInstanceRef.current) return;
audioInstanceRef.current.src = url;
audioInstanceRef.current.play();
};
这些是 Safari 发出的请求,以获取 从 Chrome 录制的音频
当我尝试玩
audio.play()
时,我在控制台中收到此错误消息。
当我尝试使用
<audio />
元素时,控制台中没有错误消息,而是触发了 stall
事件。
我还使用
File
构造函数创建了 mp3 文件并下载到 macbook。
从 Safari 录制的 mp3 文件可以播放,而从 Chrome 录制的则不能播放。
您没有正确设置内容类型标题 -
audio-mpeg
不正确。 Safari 对 Content-Type 标头非常挑剔。如果它们与音频文件的实际内容类型不匹配,则不会播放。
这就是我用于 mp3 文件的内容。请注意,Wav 和 Ogg 格式需要不同的标头。
音频/mpeg3;音频/x-mpeg-3;视频/mpeg;视频/x-mpeg;
并不是因为您将 blob 定义为“audio/mpeg”,所以它实际上会被编码为 mp3。我遇到了同样的问题...问题是 safari 实际上并没有使用相同的编解码器。
遇到了同样的问题,经过一段时间的尝试终于解决了:
上传到存储时(在我的例子中是 Firebase),输入 AND!!!文件结尾必须是 webm...
const audioBlob = new Blob(audioChunks, {type: 'audio/webm'})
const audioPath = `${filename}.webm`
const fileRef = ref(storage, audioPath)
const uploadTask = uploadBytesResumable(fileRef, audioBlob)
更新: 这仅解决了桌面版 Safari 上的问题,在 iOS 上仍然无法工作
令人惊讶的是,这些信息并未得到更广泛的传播。根据帖子here,没有一种音频格式可以在每个主要浏览器上录制和播放。
至少从我的实验来看是这样。 WebM 录制的音频适用于除 Safari 之外的所有浏览器(不过,Safari 仍然会播放一些 webms,只是不能播放使用 MediaRecorder 录制的音频。这可能是一个编码问题,但我还没有确定这一点)。
放弃 MediaRecorder 是唯一对我有用的东西。正如此评论中所述,使用不同的库(如https://github.com/closeio/mic-recorder-to-mp3)是可行的。