预加载的声音被卸载?

Posted

技术标签:

【中文标题】预加载的声音被卸载?【英文标题】:Pre-loaded sounds being unloaded? 【发布时间】:2017-07-25 14:06:44 【问题描述】:

所以,我有以下测试代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Test</title>
</head>
<body>
   <button onclick="play()">Play</button>
    <script>
        var sounds = new Array();
        preloadSnd = function()
            var snds = new Array();
            for(i = 0; i < preloadSnd.arguments.length; i++)
                snds[i] = new Audio();
                snds[i].src = preloadSnd.arguments[i];
            
            sounds.push(snds);
        
        preloadSnd(
            "test1.mp3",
            "test2.mp3",
            "test3.mp3",
            "test4.mp3",
            "test5.mp3",
            "test6.mp3",
            "test7.mp3",
            "test8.mp3"
        )
        play = function()
            sounds[0][parseInt(Math.random()*8)].play();
        
    </script>
</body>
</html>

它预加载了一些音频文件,点击一个按钮,随机播放其中一个。问题是,大约一分钟左右后,一些音频文件似乎被卸载,因为它们在播放时再次从服务器获取。这意味着一旦我的“应用程序”加载完毕,我仍然需要连接到互联网才能听到一些声音。如果我的缓存已启用,则不需要连接到互联网,但我不能依赖已启用的缓存。有什么办法可以让这些文件保持加载,这样就不需要重复获取它们?

【问题讨论】:

【参考方案1】:

您可以将所有媒体作为 Blob 获取,然后从中创建 blobURI。

这样,浏览器会将其保存在内存中(直到硬刷新或调用URL.revokeObjectURL(blobURI);

fetch("https://dl.dropboxusercontent.com/s/8c9m92u1euqnkaz/GershwinWhiteman-RhapsodyInBluePart1.mp3")
.then(r => r.blob()) // could be xhr.responseType = 'blob'
.then(blob => 
  const aud = new Audio(URL.createObjectURL(blob));
  aud.controls = true;
  document.body.appendChild(aud);
  console.log('Fully loaded and cached until the page dies...')
  );

【讨论】:

嘿,非常感谢,这完全有效。你知道是否有一些方法可以很好地回退不支持 blob 的旧浏览器?还有什么方法可以让我用一个好听的名字而不是 createObjectURL 给我的名字来引用 blob,还是我坚持只是将 URL 存储在某个地方? @SchoolBoy 设置后备,if(!('Blob' in window))fallback()。在这个后备中设置什么......我不确定。无论如何,它只会针对在 IE9 和 IE10 之间发布的浏览器,你真的有这样的受众吗? (答案中的代码是使用全新的fetch API 编写的,但正如评论所言,您也可以使用XMLHttpRequest.responseType = 'blob'。对于 blobURI,不,实际上没有办法自己设置它,但这些只有生命对于会话时间,所以我不确定您为什么需要美化它。另一种选择是 ServiceWorkers,但那是另一种野兽。 很遗憾,我的听众可能会使用 IE8 时代的旧浏览器。虽然这不是什么大问题,但它会很好。与美化相同。服务人员只会让问题变得更糟,所以......不。 :p 感谢您的帮助! IE8 不在可能的回退范围内,因为它不支持 HTMLAudioElement。 是的,我知道。我有 IE8 之类的闪存回退,所以我可以在这些情况下触发它。【参考方案2】:

看看Service Workers。

旧答案:

要不然你看localStorage了吗?

另外,请查看this blog post,了解如何在 localStorage 中存储二进制数据。

【讨论】:

本地存储如果没有大小限制就可以了。我的应用程序声音并不都适合本地存储。此外,我不需要跨会话存储声音,我只希望它们在我加载页面时加载并保持加载直到用户离开,而不是每次播放声音时再次加载。 好的,听起来很清楚。我更新了答案,也许服务人员可以帮助你。 不幸的是,这也不好,我需要它与 Safari 和 Mobile 兼容,并且服务人员支持似乎相当少。对于一个简单的问题,这似乎也是一个非常复杂的解决方案。没有更简单的方法可以在 javascript 中预加载音频吗? 没错,它现在是一种前沿。抱歉,我想我不能再帮你了。

以上是关于预加载的声音被卸载?的主要内容,如果未能解决你的问题,请参考以下文章

在移动设备上预加载音频

如何以静默方式预加载有声音的影片剪辑?

如何简单地预加载声音并在 Java 中播放?

SpriteKit:播放前将声音文件预加载到内存中?

预加载音频并在播放期间应用 css

页面卸载时显示预加载程序消息