Ionic 3:播放 Icecast/Shoutcast 音频流
Ionic 3: playing an Icecast/Shoutcast audio stream
我正在使用 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 流?您会推荐一个第三方插件以获得更好的缓冲管理和播放体验?
However, at the slightest connection drop the audio will stop and won't reconnect.
您可以通过处理 Audio 元素上的 error
事件来重新连接您自己的代码。 https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/onerror
Not to mention that if I press pause, the stream will continue using data in the background.
是的,您需要制作自己的 UI 来控制此元素。当有人暂停时,您需要调用 .stop()
。默认情况下,音频元素假设是一个在某个时刻结束的常规音频文件。
A third-party plugin...
不需要插件。
...a better buffering management and playing experience?
根据我在此回答中提出的两条建议,您可以为您的用户提供有用的体验。但是,还有两个您尚未触及的问题,您可以 运行 进入。
首先是不请求常规 ICY 元数据,也不由浏览器解码。
第二个问题是,由于浏览器将您的流视为常规音频文件,因此它还会将所有音频数据缓冲到内存中。这对于您永远不会返回并播放之前播放的音频的实时流不是很有用。 (这很少是您 运行 遇到的问题,因为音频数据需要相对较少的内存,但问题确实存在。)
这两个都是用MediaSource Extensions解决的。使用 MSE,您可以直接控制检索数据、解复用元数据以及将数据推送到缓冲区以进行回放。由于您的代码处于控制之中,因此您可以无限期地流式传输而不会发生内存泄漏。
我建议的第一件事是在您的 Icecast 服务器设置中增加 <queue-size>
和 <burst-size>
的值。
默认情况下,当客户端连接时,服务器只会向客户端发送 64kb 的音频流作为缓冲区,对于 320kbps 的 mp3 流,这不到 2 秒。
将 <audio>
元素的预加载标签设置为 none 或元数据应该可以防止暂停时无休止的数据流,或者您可以将 playbackRate
参数设置为 0.0 或更改 src
为空值,然后在音频元素上调用 .load()
以在暂停时断开客户端与流的连接。
可以通过在连接时添加额外的请求 header 让您的 Icecast 服务器将元数据直接编码到音频流中。优点是它可以很简单地将元数据更新与音频同步。
我写了一个基本的服务工作者脚本来处理这个过程,它向请求添加了必要的 header 然后解析返回的流以提取元数据并创建一个只包含音频数据的可读流传递给您的音频元素。
代码在Githubhere如果你想尝试一下。
我正在使用 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 流?您会推荐一个第三方插件以获得更好的缓冲管理和播放体验?
However, at the slightest connection drop the audio will stop and won't reconnect.
您可以通过处理 Audio 元素上的 error
事件来重新连接您自己的代码。 https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/onerror
Not to mention that if I press pause, the stream will continue using data in the background.
是的,您需要制作自己的 UI 来控制此元素。当有人暂停时,您需要调用 .stop()
。默认情况下,音频元素假设是一个在某个时刻结束的常规音频文件。
A third-party plugin...
不需要插件。
...a better buffering management and playing experience?
根据我在此回答中提出的两条建议,您可以为您的用户提供有用的体验。但是,还有两个您尚未触及的问题,您可以 运行 进入。
首先是不请求常规 ICY 元数据,也不由浏览器解码。
第二个问题是,由于浏览器将您的流视为常规音频文件,因此它还会将所有音频数据缓冲到内存中。这对于您永远不会返回并播放之前播放的音频的实时流不是很有用。 (这很少是您 运行 遇到的问题,因为音频数据需要相对较少的内存,但问题确实存在。)
这两个都是用MediaSource Extensions解决的。使用 MSE,您可以直接控制检索数据、解复用元数据以及将数据推送到缓冲区以进行回放。由于您的代码处于控制之中,因此您可以无限期地流式传输而不会发生内存泄漏。
我建议的第一件事是在您的 Icecast 服务器设置中增加 <queue-size>
和 <burst-size>
的值。
默认情况下,当客户端连接时,服务器只会向客户端发送 64kb 的音频流作为缓冲区,对于 320kbps 的 mp3 流,这不到 2 秒。
将 <audio>
元素的预加载标签设置为 none 或元数据应该可以防止暂停时无休止的数据流,或者您可以将 playbackRate
参数设置为 0.0 或更改 src
为空值,然后在音频元素上调用 .load()
以在暂停时断开客户端与流的连接。
可以通过在连接时添加额外的请求 header 让您的 Icecast 服务器将元数据直接编码到音频流中。优点是它可以很简单地将元数据更新与音频同步。
我写了一个基本的服务工作者脚本来处理这个过程,它向请求添加了必要的 header 然后解析返回的流以提取元数据并创建一个只包含音频数据的可读流传递给您的音频元素。
代码在Githubhere如果你想尝试一下。