【问题标题】:Playing audio broken into multiple files in webpage在网页中播放分成多个文件的音频
【发布时间】:2020-04-24 18:04:33
【问题描述】:

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

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

我需要使用MediaStream 对象吗?如果有,怎么做?

-谢谢

【问题讨论】:

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


    【解决方案1】:

    我会在另一个 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 为“播放器”的音频元素,例如<audio id="player"></audio>

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

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

    我希望这会有所帮助!


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


    最好的选择可能是将书籍全长和章节长度存储在 zip 文件中的 details.json 文件中,并在第一次 API 调用中将其连同每个音频文件的 URL 一起发送到客户端。这将使您能够构建一个漂亮的用户界面。

    【讨论】:

    • 绝对是正确的解决方案。除此之外,还有一些 NPM 模块可以从客户端的 ZIP 文件中提取文件。因此,如果方便地将所有内容保存在该 ZIP 中,您可以加载 ZIP 客户端,根据需要为音频提取 blob,然后从那里开始。
    • 仅供参考:此处描述的解决方案 (github.com/qawemlilo/node-streams) 可用于在没有外部模块的情况下连接音频
    【解决方案2】:

    我能想到的唯一选择是使用 javascript mp3 解码器(或将 C 解码器编译为 asm.js/wasm)并使用音频 API。或者使用 mux.js 之类的东西将 mp3 包装在 mp4 中,并使用媒体源扩展来播放。

    【讨论】:

    • 是否可行的选择是使用 Expres.js 中间件将所有文件合并到一个服务器端,然后简单地使用
    • 我的印象是这不是一个选择。但是,是的,如果您可以处理服务器端,那么还有更多选择。如果所有文件都以相同的方式编码,您可以简单地连接它们。如果没有,您可以使用 ffmpeg 连接并转换为单个文件并通过 http 播放。
    【解决方案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>
    

    【讨论】:

    • 这根本没有帮助。我不认为你读过这个问题。请删除您的答案。
    猜你喜欢
    • 2013-10-05
    • 1970-01-01
    • 2014-10-07
    • 2021-06-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多