无法在Chrome中记录音频斑点来在Safari工作



我试图在野生动物园中播放一个音频斑点,并且它播放了一秒钟,我从未听到任何音频。媒体元素发射了一个"暂停"事件,一秒钟进入播放(示例: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的方式:

  1. 添加函数 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' });
          }
    
  2. 从解码的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;
       }
    
  3. 最终将异步函数称为新变量:

       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/

最新更新