3

我正在构建一个用于离线播放一些音频文件的 Web 应用程序。我已经阅读并测试了Service Worker API 的缓存部分,我可以轻松地将所有音频文件添加到命名缓存中。<audio src='/audio/file.mp3'>但是,当我将 a 添加到 DOM 和它时,浏览器似乎没有使用它play(),即使该确切的 URL 已添加到缓存中。

在某种程度上,缓存不会自动使用是有道理的,因为这样命名缓存就没有任何意义了。

我正在使用 create-react-app,由于我没有弹出,我没有控制 Service Worker。不过,据我了解,不建议预先缓存较大的文件,因此我在 UI 中创建了一个函数,让用户决定何时缓存所有文件。

我的问题是:如何将缓存的音频文件放入音频元素中?

编辑:我认为这个问题应该可以从我的问题中理解,但被要求添加代码,所以这就是我尝试过的。

标记有一个音频元素和两个按钮。第一个按钮将 mp3 url 加载到缓存中,第二个按钮尝试两种不同的方式将其设置为音频元素的源:

  1. 从缓存的响应中插入 blob
  2. 将缓存的请求 url 设置为音频 src

当然,它们都不起作用,这就是我写这篇文章的原因。:)

<div>
    <audio src="/audio/shape_of_you.mp3" controls/>
</div>
<div>
    <button onclick="addToCache()">Add to cache</button>
    <button onclick="playCachedAudio()">Play cached audio</button>
</div>


<script>
    function addToCache() {
        caches.open('myCache').then((cache) => {
            cache.add('/audio/rise.mp3').then(() => {
                console.log('cached');
            });
        });
    }

    function playCachedAudio() {
        caches.open('myCache').then((cache) => {
            cache.match('/audio/rise.mp3').then((cachedAudio) => {
                cachedAudio.blob().then(cont => {
                    let audioEl = $('audio');
                    audioEl.attr('src', cont);
                    // ...fails with the following error in console:
                    // HTTP “Content-Type” of “text/html” is not supported. Load of media resource http://localhost:3000/[object%20Blob] failed.
                    // Cannot play media. No decoders for requested formats: text/html
                    audioEl.attr('src', '/audio/rise.mp3');
                    // Works online, but not offline (resource is not found)
                });
            });
        });
    }
</script>

我正在寻找

一种将 blob 添加为音频内容的方法

或者

另一种以编程方式强制浏览器保证缓存音频文件列表以供离线使用的方法

4

1 回答 1

5

这里提到了两个概念。缓存 API 和服务工作者。这些通常一起使用,但不是同一规范的一部分。您可以在没有 Service Worker 的情况下使用缓存 API。这正是您在提供的代码中所做的。

请注意,使用 Cache API 从不保证文件将永远保留,它仍然是缓存。但是,浏览器似乎尽最大努力保留文件。

现在,让我们看看问题所在。如果内容存储在那里,您想从缓存中加载内容,如果不是,我假设您想从网络加载它。一种解决方案是使用服务人员。Service Worker 在后台工作,拦截 fetch 事件(如果您将其配置为)。我创建了一个使用这种方法的示例应用程序源代码)。

像往常一样使用 src-attribute 配置的音频标签。然后我有一个服务工作者来监听获取事件,检查请求是否是音频文件,然后返回缓存版本或网络版本。我添加了按钮以从缓存中添加/删除文件,并添加了一个状态字段以查看它是否已添加。不需要删除按钮和状态,但很适合演示。

请注意,服务工作者使用caches.match(request)时未指定缓存名称。缓存名称仅用于对缓存项进行分组,以便开发人员维护。它使同时删除/替换许多资源变得更加容易。在开发工具中检查缓存或迭代其项目也更容易。

我无法回答如何将服务人员添加到您的特定应用程序中。请参阅 create-react-app 的文档。

于 2018-02-05T14:47:29.377 回答