android - Exoplayer 直播 - 高效的源切换
问题描述
我的 android 应用程序使用遥控器浏览一系列 http 直播流。我使用 TreeMap 将流存储为电视频道,频道号作为键。下面的代码是打开/更改源 url 的函数。我想知道您是否可以提出一种更简洁有效的方法来快速切换到另一个来源。也可能减少下一个来源的加载时间。
private void playUrl(String url) {
Uri videoUri = Uri.parse(url);
DefaultBandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
try {
player.stop();
} catch (Exception e) {
TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(bandwidthMeter);
TrackSelector trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory);
player = ExoPlayerFactory.newSimpleInstance(this, trackSelector);
PlayerView simpleExoPlayerView = findViewById(R.id.player_view);
////Set media controller
simpleExoPlayerView.setUseController(false);//set to true or false to see controllers
simpleExoPlayerView.requestFocus();
// Bind the player to the view.
simpleExoPlayerView.setPlayer(player);
}
// Measures bandwidth during playback. Can be null if not required.
// Produces DataSource instances through which media data is loaded.
DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(this, Util.getUserAgent(this, "CanaliTV2"), bandwidthMeter);
MediaSource videoSource = new HlsMediaSource(videoUri, dataSourceFactory, 1, null, null);
// Prepare the player with the source.
player.prepare(videoSource);
player.setPlayWhenReady(true); //run file/link when ready to play.
}
解决方案
这是一个困难而复杂的主题,也是我最近一直在审视自己的主题。
当您在播放器上调用 prepare 时,它会有效地重新启动它。因此,播放器当前使用的任何资源(可能是渲染器和编解码器、drm 会话等)都会被释放,然后为新流重新创建。此时数据源需要获取数据。
通过继续为每个通道调用准备,在切换“通道”后真正改善播放启动时间的唯一方法是,是否以某种方式缓存新数据源以预期切换。
我认为为了做到这一点,您需要自己的数据源工厂。编写自己的最简单的方法是首先将默认的源代码复制到您自己的类中,然后开始计算您需要进行哪些更改才能满足您的要求。
现在,您可以使用 LoadControl 缓存值来确定在播放之前将下载多少数据,并且在这样做的过程中,您会尽量减少不必要的数据传输,同时尽可能快地开始播放。- 通常建议大约 2.5 秒(Exoplayers DefaultLoadControl 开箱即用地提供此值),但根据内容 cdn 的好坏,您可能可以少用一些。
但实际上,更好、更有效的方法是不必每次都调用准备。因此,您可以通过添加新的 MediaItem 实例来操纵播放器播放列表。请参阅此处了解更多详细信息。
理论上,您实际上可以将所有频道 MediaItems 添加到同一个播放器,然后当用户更改频道时,您可以寻找下一个 MediaItem 的开头。这意味着玩家不需要重新实例化所有需要的资源,这对您来说可能更有效。
这个答案是我的意见,我可能没有提供最佳实践,但正如我所说,我最近调查了一些非常相似的事情,但在如何完成我的任务的任何硬性事实方面几乎没有成功。这就是我想出的大致轮廓。
希望能帮助到你。(抱歉有点啰嗦)
推荐阅读
- reactjs - 用户未保存到 Firestore 集合
- javascript - 什么是 location.reload() 的替代方法,因为 Codepen 不允许这样做?
- wordpress - 如何减少 WordPress 页脚
- r - R - 改变ggplot2中的形状图例(geom_col)
- javascript - Firebase 更新数据库
- python - 在 plotly 中为多个子图提供共同的图例,单击时可以隔离所有具有共同图例的迹线
- reactjs - Cytoscape 和 react-cytoscape.js-expand-collapse 错误
- mysql - 如何验证mybatis配置文件中的poolpingquery配置是否正确执行?
- google-maps - 如何在谷歌地图上找到最近的医院
- node.js - Docker 容器在主机上生成 docker 容器