在网页中播放分成多个文件的音频

时间:2020-04-24 18:04:33

标签: javascript html express html5-audio audio-streaming

我希望在网页上播放有声读物。有声书是一个.zip文件,其中包含多个.mp3文件,该书的每一章都有一个。所有文件的运行时间为几个小时,其累积大小为60MB。 .zip存储在服务器端(Express.js)

如何在客户端(例如,在<audio>元素中)连续播放每个文件,以使有声读物像1个文件一样流畅地播放?

我需要使用MediaStream对象吗?如果可以,怎么办?

-谢谢

3 个答案:

答案 0 :(得分:2)

我将在另一个Stack Overflow question上查看此答案,但是为了适应您的问题,我进行了一些修改:

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))
})

然后在屏幕上仅显示一个音频元素,其ID为“ player”,如<audio id="player"></audio>

尽管有了这个答案,arrayOfURLs数组必须包含指向服务器上API的URL,该URL将打开zip文件并返回指定的mp3数据。您可能还只想将此答案作为一般参考,而不是一个完整的解决方案,因为需要进行优化。您可能只应该首先加载第一个音频文件,并且在第一个文件结束前5分钟左右,您可能要开始预加载下一个音频文件,然后对整个过程重复此过程...您,但这有望使您站起来。

您可能还会遇到音频元素问题,因为它只会显示当前音频片段的长度,而不会显示有声读物的整个长度。我会选择相信此zip文件的书是否正确地按章分开了?如果是这样,您可以创建一个章节选择器,这几乎可以使您跳转到特定的章节,即getAudioUrls URL。

我希望这会有所帮助!


为您提供的另一条注释...阅读您对下面可能的答案的评论,您可以使用某种节点模块将所有音频文件合并为一个(audioconcat是我在快速搜索后找到的一个搜索)并将该文件返回给客户端。但是,我不会亲自走这条路,因为整个有声读物在将它们组合在一起时,将一直存储在服务器的内存中,直到将其返回给客户端为止。这可能会导致一些内存问题,因此,如果可以的话,我会避免它。但是,我承认该选项可能会很好,因为有声读物的全长将显示在音频元素的时间轴中。


最好的选择也许是将书籍的完整长度和章节长度存储在zip文件的details.json文件中,并在第一个API调用中将其连同URL一起发送到客户端,并发送到每个音频文件。这将使您能够构建一个不错的UI。

答案 1 :(得分:0)

我唯一想到的选择是使用javascript mp3解码器(或将C解码器编译为asm.js / wasm)并使用音频API。或使用mux.js之类的文件将mp3包装为mp4并使用媒体源扩展名进行播放。

答案 2 :(得分:-3)

也许这会对您有所帮助

<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>