我正在开发Ionic / Cordova应用程序,其中涉及从远程服务器加载三分钟的音频剪辑(mp3)并进行播放。
我已按照本教程http://www.html5rocks.com/en/tutorials/webaudio/intro/进行操作,并且加载和播放均正常。
但是,我想在本地存储/缓存已加载的mp3,以便用户只需下载一次即可,该应用程序可以脱机工作。这些文件约为750 KB。在下面的示例中,文件只有74 KB。
在应用程序的其他地方,我正在使用Mozilla的localForage(通过[ngular-localForage]),该状态特别声明可以用于存储ArrayBuffers-http://mozilla.github.io/localForage/#setitem
但是我似乎无法以我可以播放的格式来检索音频...我怀疑我存储了错误的东西-我真的不明白ArrayBuffer是什么!
无论如何,这是我的基本代码(目前正在使用本地文件)。
第一次加载时,音频会正确播放,第二次加载时出现错误(请参见下文):
window.AudioContext = window.AudioContext || window.webkitAudioContext;
var context = new AudioContext();
function loadDingSound() {
// attempt to retrieve stored file
$localForage.getItem('ding').then(function (response) {
if (response) {
console.log('playing audio from localForage');
console.log(response);
context.decodeAudioData(response, function(buffer) {
playSound(buffer);
});
} else {
var request = new XMLHttpRequest();
request.open('GET', 'audio/ding.mp3', true); // loading local file for now
request.responseType = 'arraybuffer';
// Decode asynchronously
request.onload = function() {
$localForage.setItem('ding', request.response).then(function () {
context.decodeAudioData(request.response, function(buffer) {
playSound(buffer);
});
});
};
request.send();
}
});
}
function playSound(buffer) {
var source = context.createBufferSource(); // creates a sound source
source.buffer = buffer; // tell the source which sound to play
source.connect(context.destination); // connect the source to the context's destination (the speakers)
source.start(0); // play the source now
}
// init
loadDingSound();
我在控制台中得到的响应如下:
Object {} // line 13
Error: Failed to execute 'decodeAudioData' on 'AudioContext': invalid ArrayBuffer for audioData. // line 15
目前,我仅在Chrome(而不是Cordova应用)中进行测试。
我究竟做错了什么?还是有更好的方法来做到这一点?也许我可以将MP3保存到文件系统中...?
最佳答案
无需执行两次从mp3压缩二进制文件到PCM原始Float类型数组的转换,因此避免两次调用encodeAudioData。另外,让我们问一个更简单的问题,因此暂时忽略localForage-只需将对原始音频缓冲区的引用停放在其自己的var中,以供以后重播:
<html>
<head>
<title>Test</title>
</head>
<body>
<script>
window.AudioContext = window.AudioContext || window.webkitAudioContext;
var audio_context = new AudioContext();
var stored_buffer = null;
function loadDingSound() {
if (stored_buffer) { // attempt to retrieve stored file
console.log('playing audio from localForage');
playSound(stored_buffer);
} else {
var request = new XMLHttpRequest();
var audio_url = "audio/ding.mp3"; // relative path to reach mp3 file
request.open('GET', audio_url, true); // loading local file for now
request.responseType = 'arraybuffer';
// Decode asynchronously
request.onload = function() {
audio_context.decodeAudioData(request.response, function(buffer) {
stored_buffer = buffer; // store buffer for replay later
playSound(buffer);
});
};
request.send();
}
}
function playSound(buffer) {
var source = audio_context.createBufferSource(); // creates a sound source
source.buffer = buffer; // tell the source which sound to play
source.connect(audio_context.destination); // connect source to speakers
source.start(0); // play the source now
}
// init
loadDingSound();
</script>
<body onkeypress="loadDingSound()">
<button onclick="loadDingSound()">play_again</button>
</body>
</html>
一旦对此感到满意,然后将其绑在localForage上-应该很快