使用localForage存储和检索音频(mp3)

时间:2015-01-12 11:48:42

标签: javascript cordova audio html5-audio localforage

我正在开发一款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是什么!< / p>

无论如何这里是我的基本代码(目前我使用的是本地文件)。 首先正确加载音频,第二次加载我得到一个错误(见下文):

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保存到文件系统......?

1 个答案:

答案 0 :(得分:0)

无需执行从mp3压缩二进制文件到PCM原始Float类型数组的转换两次,因此避免两次调用decodeAudioData。另外,让我们问一个更简单的问题,所以暂时忽略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上绑带 - 应该是快照