我试图在野生动物园中播放一个音频斑点,并且它播放了一秒钟,我从未听到任何音频。媒体元素发射了一个"暂停"事件,一秒钟进入播放(示例:0.038s(。
斑点记录在Chrome中。播放在Chrome和Firefox中正常工作。
还报告了野生动物园中媒体的持续时间比应该的短得多。例如,给定的记录为7.739秒,Chrome识别正确的持续时间,但Safari的持续时间为1.584。或另一个持续时间为9.96,但Safari报告了6.552。
我尝试确保这不是用户发起的Safari防止播放的问题。因此,播放从水龙头开始。我还尝试了不同的哑剧类型。mpeg。WebM具有H264和VP8编解码器。
我已经确保下载BLOB在Safari中的大小与Chrome上的大小相同。
我浏览了许多类似的帖子,其中包括@lastmjs通过blob URL加载音频的答案,在提供演示的情况下,在Safari中失败了。演示确实有效,我正在做更多的表现。我怀疑问题是记录的。
记录器:
self.mediaRecorder = new MediaRecorder(stream,{'audio' : {'sampleRate' : 22000}});
...assemble the chunks...
self.audioBlob = new Blob(self.audioChunks, {type: 'audio/webm; codecs=vp8'});
...upload the blob to cloud (S3)...
玩家:
...in the success handler that downloads blob...
self.audioBlob = new Blob([data],{type: 'audio/webm'});
...I later prepare the element for playback...
let audioUrl = window.URL.createObjectURL(self.audioBlob);
let audioElement = document.createElement('audio');
let sourceElement = document.createElement('source');
audioElement.muted = true;
audioElement.appendChild(sourceElement);
sourceElement.src = audioUrl;
sourceElement.type = 'audio/webm';
document.body.appendChild(audioElement);
audioElement.load()
... when the user taps on a button...
self.audioElement.muted = false;
let playPromise = self.audioElement.play();
playPromise.then(()=>{
console.log("playing should have started: " + self.audioElement.muted + " - " + self.audioElement.paused);
});
...shortly after this - the paused event handler gets fired.
没有错误消息。我正在Mac和iOS上的Safari上尝试此操作。没有错误。我也听媒体元素上的错误事件,什么也没有启动。它没有很长时间。我显然缺少一些东西。再次捕获和播放在Chrome中效果很好。播放在Firefox中起作用。但是在野生动物园的播放只是行不通的。我应该尝试什么?
您可以尝试将斑点格式更改为WAV,以使其与Safari兼容。使用库或AudioContext API可以工作。这是我在角度应用中将斑点转换为wav的方式:
-
添加函数 convertblobtowav 从Mediarecorder API中获取录制的Blob并转换为WAV格式。
async convertBlobToWav(blob: Blob): Promise<Blob> { const arrayBuffer = await new Promise<ArrayBuffer>((resolve, reject) => { const fileReader = new FileReader(); fileReader.onload = () => resolve(fileReader.result as ArrayBuffer); fileReader.onerror = reject; fileReader.readAsArrayBuffer(blob); }); const audioContext = new AudioContext(); const audioBuffer = await audioContext.decodeAudioData(arrayBuffer); const wavBuffer = this.audioBufferToWav(audioBuffer); return new Blob([wavBuffer], { type: 'audio/wav' }); }
-
从解码的blob音频数据添加AudioBufferTowav函数:
audioBufferToWav(buffer: AudioBuffer): ArrayBuffer { const numChannels = buffer.numberOfChannels; const sampleRate = buffer.sampleRate; const numFrames = buffer.length; const bytesPerSample = 2; const blockAlign = numChannels * bytesPerSample; const byteRate = sampleRate * blockAlign; const wavBuffer = new ArrayBuffer(44 + numFrames * blockAlign); const dataView = new DataView(wavBuffer); dataView.setUint32(0, 0x52494646); dataView.setUint32(4, 36 + numFrames * blockAlign, true); dataView.setUint32(8, 0x57415645); dataView.setUint32(12, 0x666d7420); dataView.setUint32(16, 16, true); dataView.setUint16(20, 1, true); dataView.setUint16(22, numChannels, true); dataView.setUint32(24, sampleRate, true); dataView.setUint32(28, byteRate, true); dataView.setUint16(32, blockAlign, true); dataView.setUint16(34, 8 * bytesPerSample, true); dataView.setUint32(36, 0x64617461); dataView.setUint32(40, numFrames * blockAlign, true); const channelData = new Array(numChannels); for (let i = 0; i < numChannels; i++) { channelData[i] = buffer.getChannelData(i); } let offset = 44; for (let i = 0; i < numFrames; i++) { for (let j = 0; j < numChannels; j++) { const sample = Math.max(-1, Math.min(1, channelData[j][i])); const int16Value = sample < 0 ? sample * 0x8000 : sample * 0x7fff; dataView.setInt16(offset, int16Value, true); offset += bytesPerSample; } } return wavBuffer; }
-
最终将异步函数称为新变量:
this.newBlob= await convertBlobToWav(this.recordedBlob)
将斑点更改为new Blob([data], {type: 'audio/mpeg'})
为我工作。
'音频/wav'和"音频/webm"不起作用。我不知道为什么,但是对于Safari 15.4仅"音频/MPEG"作品。没有此设置,您可以播放/暂停,但没有声音。
对于每个遇到相同问题的人
我遇到了同样的问题,我使用此库解决了https://github.com/muaz-khan/recordrtc。
它与使用Mediarecorder API非常相似。
截至2023/06/17,这在Safari/ios上起作用(iPados 16.3.1(。
关键部分是
let audio = document.createElement("audio");
let blob = new Blob(data, { type: "audio/mpeg" });
audio.src = window.URL.createObjectURL(blob);
res.appendChild(audio);
一个完整的例子在这里:
https://dk-minimal-mediarecorder.glitch.me/