【问题标题】:Using local file for Web Audio API in Javascript在 Javascript 中为 Web Audio API 使用本地文件
【发布时间】:2012-12-14 00:47:36
【问题描述】:

我正在尝试使用 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

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

【问题讨论】:

  • 你可能会发现这个问题的答案很有用stackoverflow.com/questions/10556437/…
  • 你考虑过本地存储吗?
  • 不知道你上面的意思。我将音频文件存储在与我的 javascript 相同的域中。只是不知道我如何访问它,或者它是否被允许?

标签: html client-side web-audio-api


【解决方案1】:

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

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/

【讨论】:

  • 难以置信。如此简单!
  • 注意:虽然这可行,但它会有明显的延迟,至少在较慢的设备上,这可能不适合游戏声音,正如 OP 所提到的。
【解决方案2】:

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

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

第一步:创建 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 请注意,为了使用我的示例,您需要删除标题部分 data:audio/mpeg;base64,

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

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

第 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 在用户交互事件发生之前会阻止任何声音播放。我需要做更多的工作来看看它的表现。

希望这可以帮助其他人摆脱我所经历的悲伤。

【讨论】:

  • 非常有趣!感谢您的详细信息。这种方法是否适用于另一个并发进程正在录制的音频文件?脱离 JS 浏览器/引擎
【解决方案3】:

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

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

【讨论】:

    【解决方案4】:

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

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

    header('Access-Control-Allow-Origin: *');
    

    【讨论】:

    • 刚刚在帖子中添加了一些细节(以及为什么我不能使用音频)
    • 感谢您的回复。添加上面给我的错误:XMLHttpRequest 无法加载文件:// beep-1.mp3/。 Access-Control-Allow-Origin 不允许 Origin null。
    • 对此还有其他想法吗?在 WAMP 上运行它时效果很好,但我希望它完全脱机(可能会使用 PhoneGap,但我现在无法使用它,因为我在 Windows 上)。我几乎正在考虑通过将文件转换为类似 Base64 编码的字符串并存储它们来破解这一步,但我不确定这是否可行?抱歉,用这个音频的东西完成菜鸟。
    • Access-Control-Allow-Origin 是一个响应头。将其添加到请求中不会有任何效果。请参阅 developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS 以了解其工作原理。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多