Я бы посмотрел этот ответ на другой вопрос переполнения стека однако я внес несколько изменений, чтобы соответствовать вашему вопросу:
var audioFileURLs= [];
function preloadAudio(url) {
var audio = new Audio();
// once this file loads, it will call loadedAudio()
// the file will be kept by the browser as cache
audio.addEventListener('canplaythrough', loadedAudio, false);
audio.src = url;
}
var loaded = 0;
function loadedAudio() {
// this will be called every time an audio file is loaded
// we keep track of the loaded files vs the requested files
loaded++;
if (loaded == audioFileURLs.length){
// all have loaded
init();
}
}
var player = document.getElementById('player');
function play(index) {
player.src = audioFiles[index];
player.play();
}
function init() {
// do your stuff here, audio has been loaded
// for example, play all files one after the other
var i = 0;
// once the player ends, play the next one
player.onended = function() {
i++;
if (i >= audioFiles.length) {
// end
return;
}
play(i);
};
// play the first file
play(i);
}
// call node/express server to get a list of links we can hit to retrieve each audio file
fetch('/getAudioUrls/#BookNameOrIdHere#')
.then(r => r.json())
.then(arrayOfURLs => {
audioFileURLs = arrayOfURLs
arrayOfURLs.map(url => preloadAudio(URL))
})
А затем просто аудиоэлемент на экране с идентификатором «player», например <audio id="player"></audio>
. С таким ответом массив arrayOfURLs
должен содержать URL-адреса API на вашем сервере, который откроет zip-файл и вернет указанные данные mp3. Вы также можете просто принять этот ответ в качестве общей справочной информации, а не в качестве полного решения, поскольку необходимо выполнить оптимизацию. Вам, вероятно, следует сначала загрузить только первый аудиофайл, и примерно за 5 минут до того, как первый файл закончится, вы можете начать предварительную загрузку следующего и затем повторить этот процесс для всего этого ... Что все будет до Вы, но это должно, надеюсь, поставить вас на ноги.
Вы также можете столкнуться с проблемой с аудиоэлементом, поскольку он будет показывать только длину текущего аудиосегмента, в котором он находится, а не полную длину аудиокниги. Я бы предпочел верить, что в этом zip-файле книга разделена главой правильно? Если это так, вы можете создать селектор глав, который в значительной степени позволяет вам перейти к указанному c главе, известному как getAudioUrls URL.
Надеюсь, это поможет!
Еще одна заметка для вас ... читая ваш комментарий к потенциальному ответу внизу, вы можете объединить все аудиофайлы в один, используя какой-то вид модуля узла ( audioconcat - тот, который я нашел после быстрого поиска в Google) и верните этот файл клиенту. Тем не менее, я бы лично не пошел по этому пути, потому что вся аудиокнига будет в памяти сервера, пока он объединяет их, и пока не вернет его клиенту. Это может вызвать проблемы с памятью в будущем, поэтому я бы избежал этого, если бы мог. Тем не менее, я признаю, что эта опция потенциально может быть полезной, потому что полная длина аудиокниги будет отображаться на временной шкале аудиоэлементов.
Возможно, лучшим вариантом будет сохранение полной длины книг и длины глав в файле подробностей. json в zip-файле и отправка его клиенту при первом вызове API вместе с URL-адресами. к каждому аудиофайлу. Это позволит вам создать приятный интерфейс.