2

我正在使用 Ionic 3 框架开发一个互联网广播应用程序。我想出了这个使用 HTML5 音频元素的简单代码。许多人认为这种方法比使用@ionic-native/streaming-media插件更好。

以下是我的实现:

HTML

<audio id="audioStream" src="http://icecastserverIP:8000/icecastchannel" autoplay></audio>

<a href="#" id="player">
  <div class="btn-play" id="con-btn-play">
    <img src="assets/img/btn-play.png" alt="Play">
  </div>
</a>

JS

$(document).ready(function(){

    var audio = $('#audioStream')[0]


    // Preloader animation

    audio.addEventListener('waiting', function () {
        $('#con-btn-play').html('<img src="assets/img/preloader.gif">');
    }, false);
    audio.addEventListener('playing', function () {
        $('#con-btn-play').html('<img src="assets/img/btn-pause.png">');
    }, false);


    // Play button behaviour

    $('#player').click(function(){
        if (audio.paused){
            audio.play();
            $('#con-btn-play').html('<img src="assets/img/btn-pause.png" alt="Pause">');
        }else {
            audio.pause();
            $('#con-btn-play').html('<img src="assets/imgs/btn-play.png" alt="Play">');
        }
    });

});

该流在 Android 和 iOS 中播放良好。但是,在最轻微的连接断开时,音频将停止并且不会重新连接。更不用说如果我按下暂停,流将继续在后台使用数据。

我的问题是:有没有更好的方法来处理 Icecast 流?您会推荐一个第三方插件以获得更好的缓冲管理和播放体验?

4

2 回答 2

2

我建议的第一件事是在您的 Icecast 服务器设置中增加 和 的<queue-size><burst-size>

默认情况下,当客户端连接时,服务器只会将 64kb 的音频流作为缓冲区发送给客户端,对于 320kbps 的 mp3 流来说,这不到 2 秒。

<audio>元素的 preload 标签设置为 none 或 metadata 应该可以防止在暂停时无休止的数据流,或者您可以将playbackRate参数设置为 0.0 或将其更改src为空值,然后调用.load()音频元素以在暂停时断开客户端与流的连接。

通过在连接时添加额外的请求标头,可以让 Icecast 服务器将元数据直接编码到音频流中。优点是可以轻松地将元数据更新与音频同步。

我编写了一个基本的服务工作者脚本来处理这个过程,它将必要的标头添加到请求中,然后解析返回的流以提取元数据并创建一个仅包含传递给您的音频元素的音频数据的可读流。

如果您想尝试一下,代码在 Github 上。

于 2018-09-06T01:54:08.587 回答
1

但是,在最轻微的连接断开时,音频将停止并且不会重新连接。

error您可以通过处理Audio 元素上 的事件来重新连接您自己的代码。https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/onerror

更不用说如果我按下暂停,流将继续在后台使用数据。

是的,您需要制作自己的 UI 来控制此元素。当有人暂停时,你会想打电话.stop()。默认情况下,音频元素假定一个在某个时间点结束的常规音频文件。

第三方插件...

不需要插件。

...更好的缓冲管理和游戏体验?

通过我在此答案中提出的两个建议,您可以为您的用户提供有用的体验。但是,您可能会遇到另外两个尚未涉及的问题。

首先是浏览器不请求常规 ICY 元数据,也不对其进行解码。

第二个问题是,由于浏览器将您的流视为常规音频文件,因此它还将所有音频数据缓冲到内存中。这对于您永远不会返回并播放以前播放的音频的实时流来说不是很有用。(这不是您遇到的问题,因为音频数据需要的内存相对较少,但问题确实存在。)

这两个都是通过使用MediaSource Extensions解决的。使用 MSE,您可以直接控制检索数据、解复用元数据以及将数据推送到缓冲区以进行回放。由于您的代码处于控制之中,因此您可以无限期地流式传输而不会发生内存泄漏。

于 2018-09-04T22:00:44.643 回答