Html 在 Javascript 中为 Web Audio API 使用本地文件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14074833/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-29 04:37:13  来源:igfitidea点击:

Using local file for Web Audio API in Javascript

htmlclient-sideweb-audio-api

提问by user1904515

I'm trying to get sound working on my iPhone game using the Web Audio API. The problem is that this app is entirely client side. I want to store my mp3s in a local folder (and without being user input driven) so I can't use XMLHttpRequest to read the data. I was looking into using FileSystem but Safari doesn't support it.

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

Is there any alternative?

有什么替代方法吗?

Edit: Thanks for the below responses. Unfortunately the Audio API is horribly slow for games. I had this working and the latency just makes the user experience unacceptable. To clarify, what I need is sounething like -

编辑:感谢以下回复。不幸的是,音频 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();

But this gives me the errors -

但这给了我错误 -

XMLHttpRequest cannot load file:///sounds/beep-1.mp3. Cross origin requests are only supported for HTTP. Uncaught Error: NETWORK_ERR: XMLHttpRequest Exception 101

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

I understand the security risks with reading local files but surely within your own domain should be ok?

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

回答by Jo?o Mosmann

I had the same problem and I found this very simple solution.

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

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" />

You can test here: http://jsfiddle.net/Tv8Cm/

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

回答by user1904515

Ok, it's taken me two days of prototyping different solutions and I've finally figured out how I can do this without storing my resources on a server. There's a few blogs that detail this but I couldn't find the full solution in one place so I'm adding it here. This may be considered a bit hacky by seasoned programmers but it's the only way I can see this working, so if anyone has a more elegent solution I'd love to hear it.

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

The solution was to store my sound files as a Base64 encoded string. The sound files are relatively small (less than 30kb) so I'm hoping performance won't be too much of an issue. Note that I put 'xxx' in front of some of the hyperlinks as my n00b status means I can't post more than two links.

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

Step 1: create Base 64 sound font

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

First I need to convert my mp3 to a Base64 encoded string and store it as JSON. I found a website that does this conversion for me here - xxxhttp://www.mobilefish.com/services/base64/base64.php You may need to remove return characters using a text editor but for anyone that needs an example I found some piano tones here - xxxhttps://raw.github.com/mudcube/MIDI.js/master/soundfont/acoustic_grand_piano-mp3.js Note that in order to work with my example you're need to remove the header part data:audio/mpeg;base64,

首先,我需要将我的 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,

Step 2: decode sound font to ArrayBuffer

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

You could implement this yourself but I found an API that does this perfectly (why re-invent the wheel, right?) - https://github.com/danguer/blog-examples/blob/master/js/base64-binary.jsResource taken from - here

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

Step 3: Adding the rest of the code

第 3 步:添加其余代码

Fairly straightforward

非常坦率的

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); });

And that's it! I have this working through my desktop version of Chrome and also running on mobile Safari (iOS 6 only of course as Web Audio is not supported in older versions). It takes a couple of seconds to load on mobile Safari (Vs less than 1 second on desktop Chrome) but this might be due to the fact that it spends time downloading the sound fonts. It might also be the fact that iOS prevents any sound playing until a user interaction event has occured. I need to do more work looking at how it performs.

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

Hope this saves someone else the grief I went through.

希望这能让其他人免于我所经历的悲伤。

回答by Jarrod

Because ios apps are sandboxed, the web view (basically safari wrapped in phonegap) allows you to store your mp3 file locally. I.e, there is no "cross domain" security issue.

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

This is as of ios6 as previous ios versions didn't support web audio api

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

回答by Avinash T.

Use HTML5 Audio tagfor playing audio file in browser.

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

Ajax request works with http protocol so when you try to get audio file using file://, browser mark this request as cross domain request. Set following code in request header -

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

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