27

我正在尝试使用 Web Audio API 在我的 iPhone 游戏上播放声音。问题是这个应用程序完全是客户端。我想将我的 mp3 存储在本地文件夹中(并且不受用户输入驱动),因此我不能使用 XMLHttpRequest 来读取数据。我正在研究使用 FileSystem 但 Safari 不支持它。

有没有其他选择?

编辑:感谢以下回复。不幸的是,音频 API 对于游戏来说非常慢。我有这个工作,延迟只是让用户体验无法接受。澄清一下,我需要的是类似 -

var request = new XMLHttpRequest();
request.open('GET', 'file:///./../sounds/beep-1.mp3', true);
request.responseType = 'arraybuffer';
request.onload = function() {
    context.decodeAudioData(request.response, function(buffer) {
    dogBarkingBuffer = buffer;
}, onError);
}
request.send();

但这给了我错误-

XMLHttpRequest 无法加载 file:///sounds/beep-1.mp3。仅 HTTP 支持跨源请求。未捕获的错误:NETWORK_ERR:XMLHttpRequest 异常 101

我了解读取本地文件的安全风险,但在您自己的域内肯定可以吗?

4

4 回答 4

44

我有同样的问题,我找到了这个非常简单的解决方案。

audio_file.onchange = function(){
  var files = this.files;
  var file = URL.createObjectURL(files[0]); 
              audio_player.src = file; 
  audio_player.play();
};
<input id="audio_file" type="file" accept="audio/*" />
<audio id="audio_player" />

你可以在这里测试:http: //jsfiddle.net/Tv8Cm/

于 2013-08-06T14:37:22.267 回答
17

好的,我花了两天时间对不同的解决方案进行原型设计,我终于弄清楚了如何在不将资源存储在服务器上的情况下做到这一点。有一些博客对此进行了详细说明,但我无法在一个地方找到完整的解决方案,因此我将其添加到此处。经验丰富的程序员可能会认为这有点 hacky,但这是我看到这个工作的唯一方法,所以如果有人有更优雅的解决方案,我很想听听。

解决方案是将我的声音文件存储为 Base64 编码字符串。声音文件相对较小(小于 30kb),所以我希望性能不会成为太大问题。请注意,我将“xxx”放在一些超链接的前面,因为我的 n00b 状态意味着我不能发布两个以上的链接。

步骤 1:创建 Base 64 声音字体

首先,我需要将我的 mp3 转换为 Base64 编码的字符串并将其存储为 JSON。我在这里找到了一个为我进行此转换的网站 - xxxhttp://www.mobilefish.com/services/base64/base64.php 您可能需要使用文本编辑器删除返回字符,但对于任何需要示例的人,我找到了一些这里的钢琴音 - xxxhttps://raw.github.com/mudcube/MIDI.js/master/soundfont/acoustic_grand_piano-mp3.js 请注意,为了使用我的示例,您需要删除标题部分数据:音频/mpeg;base64,

第 2 步:将声音字体解码为 ArrayBuffer

你可以自己实现它,但我找到了一个完美的 API(为什么要重新发明轮子,对吧?) - https://github.com/danguer/blog-examples/blob/master/js/base64-binary。 js 资源取自 -这里

第 3 步:添加其余代码

非常坦率的

var cNote  = acoustic_grand_piano.C2;
var byteArray = Base64Binary.decodeArrayBuffer(cNote); 
var context = new webkitAudioContext();

context.decodeAudioData(byteArray, function(buffer) {
    var source = context.createBufferSource(); // creates a sound source
    source.buffer = buffer;    
    source.connect(context.destination); // connect the source to the context's destination (the speakers)
    source.noteOn(0); 
}, function(err) { console.log("err(decodeAudioData): "+err); });

就是这样!我通过我的桌面版 Chrome 和移动版 Safari 运行(当然仅限 iOS 6,因为旧版本不支持 Web 音频)。在移动版 Safari 上加载需要几秒钟(在桌面版 Chrome 上加载不到 1 秒),但这可能是因为它需要花费时间下载声音字体。也可能是因为 iOS 在用户交互事件发生之前会阻止任何声音播放。我需要做更多的工作来看看它的表现。

希望这能拯救别人我所经历的悲伤。

于 2012-12-29T16:05:35.610 回答
1

因为 ios 应用程序是沙盒化的,所以 web 视图(基本上是 safari 包装在 phonegap 中)允许您在本地存储您的 mp3 文件。即,不存在“跨域”安全问题。

这是 ios6 的版本,因为以前的 ios 版本不支持网络音频 api

于 2013-03-03T00:13:37.970 回答
-2

使用HTML5 Audio 标签在浏览器中播放音频文件。

Ajax 请求适用于 http 协议,因此当您尝试使用 file:// 获取音频文件时,浏览器会将此请求标记为跨域请求。在请求标头中设置以下代码 -

header('Access-Control-Allow-Origin: *');
于 2012-12-28T19:47:28.040 回答