Воспроизведение аудио разбито на несколько файлов на веб-странице - PullRequest
1 голос
/ 24 апреля 2020

Я хочу воспроизвести аудиокнигу на моей веб-странице. Аудиокнига представляет собой файл .zip, который содержит несколько файлов .mp3, по одному на каждую главу книги. Время выполнения всех файлов составляет несколько часов, а их совокупный размер составляет 60 МБ. .Zip хранится на стороне сервера (Express. js)

Как воспроизвести каждый файл подряд на клиенте (например, в элементе <audio>), чтобы аудиокнига воспроизводится плавно, как будто 1 файл?

Нужно ли использовать MediaStream объект? Если да, то как?

-Спасибо

Ответы [ 3 ]

2 голосов
/ 25 апреля 2020

Я бы посмотрел этот ответ на другой вопрос переполнения стека однако я внес несколько изменений, чтобы соответствовать вашему вопросу:

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-адресами. к каждому аудиофайлу. Это позволит вам создать приятный интерфейс.

0 голосов
/ 24 апреля 2020

Единственные варианты, которые я могу придумать, - это использовать либо mp3-декодер javascript (или скомпилировать C декодер для asm.js / wasm), либо использовать аудио API. Или оберните mp3 в mp4, используя что-то вроде mux. js и используйте расширения медиаисточников для воспроизведения.

0 голосов
/ 24 апреля 2020

может быть, это поможет вам

<audio controls="controls">
  <source src="track.ogg" type="audio/ogg" />
  <source src="track.mp3" type="audio/mpeg" />
Your browser does not support the audio element.
</audio>
...