通过Blob URL加载音频在Safari中失败

时间:2012-11-05 12:14:52

标签: safari blob html5-audio

以下代码适用于Chrome(22.0)但不适用于Safari(6.0)

<!DOCTYPE html>
<html>
<head>
<script>
function onGo(e) {
  var fr = new FileReader();
  var file = document.getElementById("file").files[0];
  fr.onload = function(e) {
      var data = new Uint8Array(e.target.result);
      var blob = new Blob([data], {type: 'audio/mpeg'});
      var audio = document.createElement('audio'); 
      audio.addEventListener('loadeddata', function(e) { 
          audio.play();
        }, false);
      audio.addEventListener('error', function(e) {
          console.log('error!', e);
        }, false);
      audio.src = webkitURL.createObjectURL(blob);    
    };
  fr.readAsArrayBuffer(file);
}
</script>
</head>
<body>
  <input type="file" id="file" name="file" />
  <input type="submit" id="go" onclick="onGo()" value="Go" />
</body>
</html>

在Safari中,既不会调用回调(loadeddata也不会出错)。 使用的内容是一个mp3文件,通常用音频标签回放。 Safari需要特别小心吗?

3 个答案:

答案 0 :(得分:3)

我遇到了同样的问题,我已经花了几天时间对其进行故障排除。 正如其他帖子中提到的 pwray 一样,Safari需要媒体请求的文件扩展名:

HTML5 Audio files fail to load in Safari

我试图将我的blob保存到一个文件中,将其命名为file.mp3并且Safari能够以这种方式加载音频,但是在我将文件重命名为没有扩展名(只是“文件”)之后,它没有加载。 当我在Safari中的另一个标签中尝试从blob创建的url时:

url = webkitURL.createObjectURL(blob);

它立即下载一个名为“unknown”的文件,但是当我在Chrome中尝试相同的东西时(也在Mac上),它在浏览器中显示了该文件的内容(mp3文件以ID3开头,然后是一堆不可读的字符)。 我无法弄清楚如何强制blob制作的url有一个扩展名,因为通常它看起来像这样:

blob:https://example.com/a7e38943-559c-43ea-b6dd-6820b70ca1e2

所以它的结尾看起来像一个会话变量。

这是我陷入困境的地方,我真的希望看到一些聪明人的解决方案。 谢谢, 史蒂芬

答案 1 :(得分:0)

有时,HTML5音频可以在没有任何明显原因的情况下停止加载。 如果你看一下媒体事件(http://www.w3schools.com/tags/ref_eventattributes.asp),你会看到一个名为“ onStalled ”的事件,定义是“当浏览器无法获取时要运行的脚本无论出于什么原因,媒体数据“似乎对你有用。

尝试侦听该事件并在必要时重新加载文件,如下所示:

audio.addEventListener('onstalled', function(e) { 
      audio.load();
    }, false);

我希望它有所帮助!

答案 2 :(得分:0)

很多年后,我相信OP中的示例应该可以正常工作。只要您在创建Blob时以某种方式设置了mime类型,就像上面的OP那样使用传入的选项的type属性:

new Blob([data], {type: 'audio/mpeg'});

您还可以在音频元素内部使用<source>元素,并设置type元素的<source>属性。我在这里有一个示例:

https://lastmjs.github.io/safari-object-url-test

这是代码:

const response = await window.fetch('https://upload.wikimedia.org/wikipedia/commons/transcoded/a/ab/Alexander_Graham_Bell%27s_Voice.ogg/Alexander_Graham_Bell%27s_Voice.ogg.mp3');

const audioArrayBuffer = await response.arrayBuffer();
const audioBlob = new Blob([audioArrayBuffer]);
const audioObjectURL = window.URL.createObjectURL(audioBlob);

const audioElement = document.createElement('audio');

audioElement.setAttribute('controls', true);
document.body.appendChild(audioElement);

const sourceElement = document.createElement('source');

audioElement.appendChild(sourceElement);

sourceElement.src = audioObjectURL;
sourceElement.type = 'audio/mp3';

我更喜欢在创建Blob时设置其mime类型。 <source>元素src的属性/属性无法动态更新。