ExoPlayer 2 的质量选择器

2024-01-06

我目前正在开发一个现场和电影播放器​​应用程序。我选择了Exo播放器版本2播放这部电影,我对此了解不多。我想让用户选择电影的质量在播放器屏幕上,例如 720p 或 1080p 等。 但我不知道如何获取现有品质的列表并将其显示给用户。 下面的代码是我对 SimpleExoPlayer 的实现:

private void initPlayer(String path){
    Handler handler = new Handler();
    // 1. Create a default TrackSelector
    BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
    TrackSelection.Factory videoTrackSelectionFactory =
            new AdaptiveVideoTrackSelection.Factory(bandwidthMeter);
    TrackSelector trackSelector =
            new DefaultTrackSelector(videoTrackSelectionFactory);

    // 2. Create a default LoadControl
    LoadControl loadControl = new DefaultLoadControl();
    // 3. Create the player
    player = ExoPlayerFactory.newSimpleInstance(this, trackSelector, loadControl);

    SimpleExoPlayerView playerView = (SimpleExoPlayerView) findViewById(R.id.player_view);
    playerView.setPlayer(player);
    playerView.setKeepScreenOn(true);
    // Produces DataSource instances through which media data is loaded.
    DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(this, Util.getUserAgent(this, "ExoPlayer"));

    // This is the MediaSource representing the media to be played.
    MediaSource videoSource = new HlsMediaSource(Uri.parse(path),
            dataSourceFactory,handler, null);
    // Prepare the player with the source.
    player.addListener(this);
    player.prepare(videoSource);
    playerView.requestFocus();
    player.setPlayWhenReady(true); // to play video when ready. Use false to pause a video
}

// ExoPlayer Listener Methods :
@Override
public void onTimelineChanged(Timeline timeline, Object manifest) {

}

@Override
public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {

}

@Override
public void onLoadingChanged(boolean isLoading) {

}

@Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
    switch (playbackState) {
        case ExoPlayer.STATE_BUFFERING:
            //You can use progress dialog to show user that video is preparing or buffering so please wait
            progressBar.setVisibility(View.VISIBLE);
            break;
        case ExoPlayer.STATE_IDLE:
            //idle state
            break;
        case ExoPlayer.STATE_READY:
            // dismiss your dialog here because our video is ready to play now
            progressBar.setVisibility(GONE);
            //Toast.makeText(getApplicationContext(),String.valueOf(player.getCurrentTrackSelections().get(0).getSelectedFormat().bitrate),Toast.LENGTH_SHORT).show();
            break;
        case ExoPlayer.STATE_ENDED:
            // do your processing after ending of video
            break;
    }
}

@Override
public void onPlayerError(ExoPlaybackException error) {
    // show user that something went wrong. it can be a dialog
}

@Override
public void onPositionDiscontinuity() {

}

请帮助解决这个问题。 多谢。


您想要实现的一切都可以在 ExoPlayer2 中查看demo app https://github.com/google/ExoPlayer。更具体地说PlayerActivity https://github.com/google/ExoPlayer/blob/release-v2/demos/main/src/main/java/com/google/android/exoplayer2/demo/PlayerActivity.java class.

你也可以看看这个好文章 https://medium.com/google-exoplayer/exoplayer-2-x-track-selection-2b62ff712cc9关于这个话题。

您需要研究的核心点是围绕曲目选择(通过TrackSelector)以及TrackSelectionHelper。我将在下面提供重要的代码示例,希望这些示例足以帮助您继续前进。但最终,只需遵循演示应用程序中类似的操作即可到达您需要的位置。

您将保留启动播放器时使用的曲目选择器,并将其用于几乎所有事情。

下面只是一段代码,理想地涵盖了您想要做的事情的要点,因为该演示似乎确实使事情变得过于复杂。我还没有运行代码,但它已经足够接近了。

// These two could be fields OR passed around
int videoRendererIndex;
TrackGroupArray trackGroups;

// This is the body of the logic for see if there are even video tracks
// It also does some field setting
MappedTrackInfo mappedTrackInfo = trackSelector.getCurrentMappedTrackInfo();
for (int i = 0; i < mappedTrackInfo.length; i++) {
  TrackGroupArray trackGroups = mappedTrackInfo.getTrackGroups(i);
  if (trackGroups.length != 0) {
    switch (player.getRendererType(i)) {
      case C.TRACK_TYPE_VIDEO:
        videoRendererIndex = i;
        return true;
    }
  }
}

// This next part is actually about getting the list. It doesn't include
// some additional logic they put in for adaptive tracks (DASH/HLS/SS),
// but you can look at the sample for that (TrackSelectionHelper#buildView())
// Below you'd be building up items in a list. This just does
// views directly, but you could just have a list of track names (with indexes)
for (int groupIndex = 0; groupIndex < trackGroups.length; groupIndex++) {
  TrackGroup group = trackGroups.get(groupIndex);
  for (int trackIndex = 0; trackIndex < group.length; trackIndex++) {
    if (trackIndex == 0) {
      // Beginning of a new set, the demo app adds a divider
    }
    CheckedTextView trackView = ...; // The TextView to show in the list
    // The below points to a util which extracts the quality from the TrackGroup
    trackView.setText(DemoUtil.buildTrackName(group.getFormat(trackIndex)));
}

// Assuming you tagged the view with the groupIndex and trackIndex, you
// can build your override with that info.
Pair<Integer, Integer> tag = (Pair<Integer, Integer>) view.getTag();
int groupIndex = tag.first;
int trackIndex = tag.second;
// This is the override you'd use for something that isn't adaptive.
override = new SelectionOverride(FIXED_FACTORY, groupIndex, trackIndex);
// Otherwise they call their helper for adaptives, which roughly does:
int[] tracks = getTracksAdding(override, trackIndex);
TrackSelection.Factory factory = tracks.length == 1 ? FIXED_FACTORY : adaptiveTrackSelectionFactory;
override = new SelectionOverride(factory, groupIndex, tracks);

// Then we actually set our override on the selector to switch the quality/track
selector.setSelectionOverride(rendererIndex, trackGroups, override);

正如我上面提到的,这个过程有点过于简单化,但核心部分是你在搞乱TrackSelector, SelectionOverride, and Track/TrackGroups让它发挥作用。

可以想象,您可以逐字复制演示代码,它应该可以工作,但我强烈建议花时间了解每个部分的作用,并根据您的用例定制您的解决方案。

如果我有更多时间,我会编译并运行它。但如果您可以使用我的示例,请随意编辑我的帖子。

希望有帮助:)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ExoPlayer 2 的质量选择器 的相关文章

  • 计算Android设备的PPI

    如何计算 Android 设备的 PPI 最特别的是 Android 平板电脑 请注意 我想计算设备的 PPI 而不是 DPI 就像一二三一样简单 让我们来计算一下PPI to Nexus 5 例如 float LCD Diagonal 4
  • onBeaconServiceConnect 未调用

    和以前一样 我使用 Android Beacon 库 它已经工作了 我可以通过 BLE 低功耗蓝牙找到信标 但是现在 更新到最新版本的库后 现在方法onBeaconServiceConnect 不再跑了 请告诉我我需要做什么才能让它发挥作用
  • 使用 google Directions API 的地图视图绘制方向 - 解码折线

    我正在尝试使用 Google 方向 API 在我的地图视图上显示方向 但我在从 JSON 响应获取数据时遇到困难 我可以获得 级别 和 点 字符串 但无法弄清楚如何将它们解码为地图上的点 任何帮助将非常感激 我有一个类可以为您解码它们 添加
  • Android 上的 SVG 支持

    Android 支持 SVG 吗 有什么例子吗 最完整的答案是这样的 Android 2 x 默认浏览器本身不支持 SVG Android 3 默认浏览器支持 SVG 要将 SVG 支持添加到 2 x 版本的平台 您有两个基本选择 安装功能
  • Service 和 IntentService,运行从服务器轮询数据库值的服务哪个更好?

    我读过很多关于Service and IntentService 然而 当做出决定时 我没有足够的信心选择使用哪种类型来创建一个后台服务 该服务将在一定时间间隔内从数据库轮询数据 并在获得所需数据时停止它 因为数据代表请求的状态 例如 订购
  • 安卓定位不准确

    我正在尝试获取当前用户的位置 我试图重构我的代码以获得更好的结果 但我只是不断得到关于准确度的荒谬位置 它在 900 600 米之间 如何才能得到更好的结果 使其精度达到50m以内 这是我的代码 package com agam mapsl
  • 带操作按钮的颤动本地通知

    我在我的 flutter 项目中尝试了 flutter 本地通知插件 它在简单通知上工作正常 但我需要带有操作按钮的通知功能 请帮助我或建议我实现此功能 不幸的是 flutter local notifications 插件尚不支持操作按钮
  • 调试:在 Android 1.0 中找不到文件

    今天我更新到 Android Studio v 1 0 在尝试编译任何项目时出现以下错误 app build intermediates classes debug 找不到文件 问题是在更新之前我没有任何问题 这是我实际尝试编译的代码 构建
  • Android 自定义布局 - onDraw() 永远不会被调用

    public class MainActivity extends Activity Override public void onCreate Bundle savedInstanceState super onCreate savedI
  • 如何在手机缓存中保存用户名和密码

    我有一个用户登录应用程序 它需要用户的电子邮件和密码 我想将电子邮件和密码保存在手机缓存中 以便用户不必再次输入 有什么办法可以将数据保存在Android缓存中吗 我认为你需要使用SharedPreference用于在设备中使用应用程序时保
  • 如何检查用户在EditText中输入自己的电话号码?

    用户将在我的 Android 应用程序的注册页面上的编辑文本中输入手机号码 如何检查用户输入的是他 她的手机号码而不是其他人的 我试过这个 TelephonyManager tMgr TelephonyManager mAppContext
  • 如何在 Android 模块中使用 FirebaseAuth

    我正在开发一个聊天库 我想在其中显示登录用户的对话 制作该库的原因是我想将其集成到多个项目中 我现在面临的问题是FirebaseAuth表示用户尚未登录 FirebaseAuth getInstance mFirebaseApp getCu
  • 获取手机的 z 轴和磁北极(而不是 y 轴)之间的角度

    我知道如何使用 getOrientation 方法获取手机 y 轴和磁北之间的方向角 如此处所述https developer android com guide topics sensors sensors position https
  • 在游戏视图下添加 admob

    我一直试图将 admob 放在我的游戏视图下 这是我的代码 public class HoodStarGame extends AndroidApplication Override public void onCreate Bundle
  • HERE 地图:更改路线已行驶部分的颜色

    导航时可以改变路线的颜色吗 具体来说 我希望路线中已行驶的部分的颜色与即将行驶的部分的颜色不同 现在都是同一个颜色 将 MapRoute 对象的 TravelColor 变量设置为透明对我来说很有效 mapRoute color Resou
  • react-native run-android 失败并出现错误:任务 ':app:dexDebug' 执行失败

    我使用的是 Windows 8 1 和react native cli 1 0 0 and react native 0 31 0 添加后react native maps对于该项目 我运行了命令react native upgrade并给
  • 如何修改 Skobbler 注释而不重新添加它

    我必须修改 SKAnnotation 的图像 注释生成器代码 private SKAnnotation getAnnotationFromView int id int minZoomLvl View view SKAnnotation a
  • 按钮 - 单击时更改背景颜色

    我的活动中有 8 个按钮 我正在寻找的是 按钮具有默认背景 单击按钮时 背景颜色应更改为其他颜色 这部分非常简单 但是 当我单击任何其他按钮时 第一个按钮的背景颜色应该变回默认颜色 我知道这将使用 选择器状态 来完成 但我不太确定如何实现它
  • 模块中的类无法加载

    我正在开发一个 2D Unity android 游戏 其中我最近添加了 Firebase Beta SDK 但添加后FirebaseAnalytics unitypackage我面临的错误是 无法加载模块中的类 当我删除文件夹时Fireb
  • Android 中循环事件的星期几和时间选择器

    我想创建一个控件 允许用户在我的 Android 活动中选择一周中的某一天 星期一 和一天中的某个时间 下午 1 00 找不到任何关于此的好帖子 好吧 我想我已经明白了 我只是不喜欢这个解决方案 因为我在一周中的某一天使用的微调器与时间选择

随机推荐

  • Firefox 插件 CPU 使用率

    我需要在 Web 开发编码会话期间收集有关 Firefox CPU 使用情况的数据 并且我想知道是否可以监视特定 Firefox 插件的 CPU 使用情况 现在我正在使用 Windows 的 perfmon msc 但它只允许我监视整个 F
  • 匹配目录路径(不包括文件路径)的正则表达式

    我正在寻找 IIS 所需的正则表达式模式 基本上我希望它匹配任何目录路径但拒绝文件路径 我到处寻找但运气不佳 示例 匹配 directory content css 匹配 directory content css 拒绝 directory
  • 加载器在 chrome 中的同步 ajax 调用期间不工作

    加载程序在 google chrome 中的同步 异步 假 ajax 调用期间不工作 在 Firefox 和 IE 中工作正常 在我的调试测试期间 Loader 显示直到 ajax 请求开始 当请求发送到服务器时被删除或消失 我在服务器上保
  • 如何在Matlab中增量训练神经网络?

    假设我有很大的训练集 导致 Matlab 在训练时挂起 或者没有足够的内存来容纳训练集 是否可以将训练集分成几部分并逐部分训练网络 是否可以一次用一个样本 一个一个 来训练网络 您可以手动将数据集分成批次并逐一训练它们 for bn 1 n
  • Hibernate 查询获取日期记录忽略时间戳

    我在 DB Oracle 表之一中有一个时间戳列 tradedate 我使用 hibernate 作为持久层来获取数据并将其存储到数据库 我有一个要求 我需要按日期查询数据库 即 用户从 UI 传递一个日期 我需要根据该日期获取过滤后的数据
  • 如何使用 jquery html 和 php 将标签插入数据库

    我想将这些特定标签插入数据库 这是我的 HTML div div
  • OSX 上的 QT:托盘图标 - 图标停靠问题

    我的目的是创建一个没有自动显示主窗口的 QT 托盘应用程序 这个应用程序的启动是一个带有菜单的托盘图标 问题是我的停靠图标仍然显示在我的应用程序中 我的问题是 1 如何防止出现 Dock 图标 2 如果答案涉及将条目添加到生成的 pfile
  • 有没有办法将图像作为位图加载到 Glide

    我正在寻找一种使用位图作为 Glide 输入的方法 我什至不确定这是否可能 这是为了调整大小的目的 Glide 具有良好的图像缩放增强功能 问题是我的资源作为位图已经加载到内存中 我能找到的唯一解决方案是将图像存储到临时文件并将它们作为 i
  • ImportError:无法从“azure.servicebus”导入名称“ServiceBusClient”

    我想运行一个简单的 Azure 服务总线程序 我收到以下错误 ImportError cannot import name ServiceBusMessage from azure servicebus 当我在互联网上搜索时 我应该安装Az
  • 如何从倒数计时器完成方法调用另一个意图?

    我正在做 Android 测验 在我的代码中 我有倒计时器 当时间结束时 我希望下一个问题出现并且分数减少 对于分数递减 currentGame decrementScore 方法 如果我在计时器的 finish 方法中添加以下代码 它工作
  • 不存在的属性 HTML 输入字段

    将不存在的属性附加到 html 元素以便在 jquery 中使用它是一个好习惯吗 例如
  • 如何从另一个线程使用服务器更新java swing gui?

    我有一个 Java Swing 应用程序 每当传入的客户端尝试建立连接时 它都会启动一个新线程 该线程使用执行程序池来打开套接字服务器 该应用程序需要两个按钮 一个用于启动服务器 另一个用于停止服务器 我想要的是显示服务器状态 并禁用相反的
  • COM 自动化接口中允许的“out”参数类型

    我正在为应用程序实现 COM 自动化 双接口 自动化接口将从 VBScript 调用 我不太清楚该方法的参数允许使用哪些类型 我确实知道价值观基本上必须符合VARIANT 但这是否意味着每个类型的参数int必须通过一个VARIANT 或者可
  • 如何在Python中将元组的元组转换为pandas.DataFrame?

    如果问题太基本 也没有冒犯的意思 如果您需要更多信息 请与我们联系 我正在寻找一种想法 以干净 高效 Pythonic 的方式将方形元组转换为 pandas DataFrame 即来自 s 1 0 0 0 2 3 0 0 4 5 6 0 7
  • 在 Hibernate 中使用 Spring Data 查询时出现 NoViableAltException

    我正在使用指定 Spring Data 查询 Query在存储库方法上 但它抛出了NoViableAltException例外 这是我正在使用的存储库接口方法和注释 Query value SELECT one saveLine two s
  • 对 Julia 中的内存分配和垃圾收集感到困惑

    我对 Julia 中的内存分配有点困惑 我从常见问题解答中知道 http julia readthedocs org en latest manual faq 清除大变量使用的内存是通过将其设置为较小的值 例如 0 然后运行来完成的gc 但
  • Mac OS X 上带有 Cocoa WebView 的综合 Web 服务器

    我想创建一个 Webview 我可以完全控制它加载的内容 本质上 我想提供一个类的实例 它扮演 URL 中指定的各种 Web 服务器的角色 理想情况下 我会为这个 webview 提供一个委托 它会告诉委托它需要的每个 URL 并且委托将使
  • 卓:0.0.0.0/0 和 ::/0 是什么意思?

    在安全组中 我添加的每个入站端口都添加了两条规则 一条为 0 0 0 0 0 另一条为 0 它们分别是什么意思 Internet 协议版本 4 IPv4 中的默认路由被指定 作为 CIDR 表示法中的零地址 0 0 0 0 0 通常称为 四
  • Angular 反应式表单集和清除验证器

    请协助 我想删除表单中的所有验证器 请告知是否可能 如果不可能 如果您有一个包含 20 个或更多表单控件的表单组 删除验证器的更好方法是什么 请参阅下面的示例 ngOnInit this exampleFormGroup this form
  • ExoPlayer 2 的质量选择器

    我目前正在开发一个现场和电影播放器 应用程序 我选择了Exo播放器版本2播放这部电影 我对此了解不多 我想让用户选择电影的质量在播放器屏幕上 例如 720p 或 1080p 等 但我不知道如何获取现有品质的列表并将其显示给用户 下面的代码是