koj*_*ow7 5 javascript safari audio ios reactjs
我有一个语言网站,我正在致力于教授语言。用户可以单击对象并听到他们单击的内容的音频。许多将使用它的人位于互联网连接速度较慢的偏远地区。因此,我需要在加载每个活动之前缓存音频,否则会有太多延迟。
以前,我遇到了预加载不起作用的问题,因为 iOS 设备不允许在没有单击事件的情况下加载音频。我已经解决了这个问题,但是,我现在有另一个问题。iOS/Safari只允许加载最新的音频文件。因此,每当用户点击另一个音频文件(即使之前点击过),它不会被缓存,浏览器必须再次下载它。
到目前为止,我还没有找到合适的解决方案。2011~2012 年左右有很多帖子试图解决这个问题,但我还没有找到好的解决方案。一种解决方案是将活动的所有音频剪辑合并到一个音频文件中。这样,每个活动只会将一个音频文件加载到内存中,然后您只需选择音频文件的特定部分即可播放。虽然这可能有效,但每当需要更改、添加或删除音频剪辑时,它也会变得令人讨厌。
我需要在ReactJS/Redux环境中运行良好并在 iOS 设备上正确缓存的东西。
是否有 2020 年有效的解决方案?
您可以使用IndexedDB. 它是用于客户端存储大量结构化数据(包括文件/blob)的低级 API。IndexedDBAPI 很强大,但对于简单的情况来说似乎太复杂了。如果你喜欢一个简单的API,尽量库,比如localForage,dexie.js。
localForage 是一个 Polyfill,为客户端数据存储提供简单的 name:value 语法,它在后台使用 IndexedDB,但在不支持 IndexedDB 的浏览器中回退到 WebSQL,然后使用 localStorage。
您可以在IndexedDB此处查看浏览器支持:https : //caniuse.com/#search=IndexedDB。它得到了很好的支持。这是我用来展示这个概念的一个简单例子:
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Audio</title>
</head>
<body>
<h1>Audio</h1>
<div id="container"></div>
<script src="localForage.js"></script>
<script src="main.js"></script>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)
main.js
"use strict";
(function() {
localforage.setItem("test", "working");
// create HTML5 audio player
function createAudioPlayer(audio) {
const audioEl = document.createElement("audio");
const audioSrc = document.createElement("source");
const container = document.getElementById("container");
audioEl.controls = true;
audioSrc.type = audio.type;
audioSrc.src = URL.createObjectURL(audio);
container.append(audioEl);
audioEl.append(audioSrc);
}
window.addEventListener("load", e => {
console.log("page loaded");
// get the audio from indexedDB
localforage.getItem("audio").then(audio => {
// it may be null if it doesn't exist
if (audio) {
console.log("audio exist");
createAudioPlayer(audio);
} else {
console.log("audio doesn't exist");
// fetch local audio file from my disk
fetch("panumoon_-_sidebyside_2.mp3")
// convert it to blob
.then(res => res.blob())
.then(audio => {
// save the blob to indexedDB
localforage
.setItem("audio", audio)
// create HTML5 audio player
.then(audio => createAudioPlayer(audio));
});
}
});
});
})();
Run Code Online (Sandbox Code Playgroud)
localForage.js只包含这里的代码:https : //github.com/localForage/localForage/blob/master/dist/localforage.js
您可以检查IndexedDBchrome 开发工具,您会在那里找到我们的项目:
如果你刷新页面,你仍然会在那里看到它,你也会看到创建的音频播放器。我希望这回答了你的问题。
顺便说一句,如果仍然可以存储音频文件,那么旧版本的 safari IOS 不支持存储blob,IndexedDB因为ArrayBuffer它得到了很好的支持。这是一个使用示例ArrayBuffer:
main.js
"use strict";
(function() {
localforage.setItem("test", "working");
// convert arrayBuffer to Blob
function arrayBufferToBlob(buffer, type) {
return new Blob([buffer], { type: type });
}
// convert Blob to arrayBuffer
function blobToArrayBuffer(blob) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.addEventListener("loadend", e => {
resolve(reader.result);
});
reader.addEventListener("error", reject);
reader.readAsArrayBuffer(blob);
});
}
// create HTML5 audio player
function createAudioPlayer(audio) {
// if it's a buffer
if (audio.buffer) {
// convert it to blob
audio = arrayBufferToBlob(audio.buffer, audio.type);
}
const audioEl = document.createElement("audio");
const audioSrc = document.createElement("source");
const container = document.getElementById("container");
audioEl.controls = true;
audioSrc.type = audio.type;
audioSrc.src = URL.createObjectURL(audio);
container.append(audioEl);
audioEl.append(audioSrc);
}
window.addEventListener("load", e => {
console.log("page loaded");
// get the audio from indexedDB
localforage.getItem("audio").then(audio => {
// it may be null if it doesn't exist
if (audio) {
console.log("audio exist");
createAudioPlayer(audio);
} else {
console.log("audio doesn't exist");
// fetch local audio file from my disk
fetch("panumoon_-_sidebyside_2.mp3")
// convert it to blob
.then(res => res.blob())
.then(blob => {
const type = blob.type;
blobToArrayBuffer(blob).then(buffer => {
// save the buffer and type to indexedDB
// the type is needed to convet the buffer back to blob
localforage
.setItem("audio", { buffer, type })
// create HTML5 audio player
.then(audio => createAudioPlayer(audio));
});
});
}
});
});
})();
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
716 次 |
| 最近记录: |