带有起始音轨的短跑自适应播放,怎么样?

时间:2018-02-23 13:25:44

标签: exoplayer exoplayer2.x

我有三种方法可以在我的应用中播放自适应短划线视频:

  1. 修正视频和音轨
  2. 自适应视频和音轨
  3. 自适应视频和音频曲目(带有起始曲目)
  4. 前两种方式完美运行,但第三种方法表现得很奇怪

    我正在做的是首先在'onTracksChanged'方法上设置起始曲目。一旦玩家调用onLoadingChanged(false)方法,我想删除起始曲目的选择并让玩家选择最佳曲目。为了删除所选择的我正在调用trackSelector.clearSelectionOverrides(),但是这完全删除了缓冲区,视频停止并开始在最佳轨道中缓冲。

    enter image description here

    我想要实现的行为是以下

    选择起始曲目(让我们假设144p) - >加载第一个块 - >删除144p的选择 - >继续播放144p中的剩余缓冲区,同时开始加载到最佳轨道。

    我怎样才能实现它?

2 个答案:

答案 0 :(得分:2)

您可以使用AdaptiveTrackSelection执行此操作,并将除要保留的轨道之外的所有轨道列入黑名单。要实现这一点,最简单的方法是提供自己的TrackSelection.Factory。

public class StartupTrackSelectionFactory implements TrackSelection.Factory {

  // end blacklisting after ten seconds earliest
  private static final long BLACKLIST_DURATION = 10 * 1000;

  private final BandwidthMeter bandwidthMeter;

  public StartupTrackSelectionFactory(BandwidthMeter bandwidthMeter) {
    this.bandwidthMeter = bandwidthMeter;
  }

  @Override
  public TrackSelection createTrackSelection(TrackGroup group, int... tracks) {
    AdaptiveTrackSelection adaptiveTrackSelection = new AdaptiveTrackSelection(
        group,
        tracks,
        bandwidthMeter,
        AdaptiveTrackSelection.DEFAULT_MAX_INITIAL_BITRATE,
        AdaptiveTrackSelection.DEFAULT_MIN_DURATION_FOR_QUALITY_INCREASE_MS,
        AdaptiveTrackSelection.DEFAULT_MAX_DURATION_FOR_QUALITY_DECREASE_MS,
        AdaptiveTrackSelection.DEFAULT_MIN_DURATION_TO_RETAIN_AFTER_DISCARD_MS,
        AdaptiveTrackSelection.DEFAULT_BANDWIDTH_FRACTION,
        AdaptiveTrackSelection.DEFAULT_BUFFERED_FRACTION_TO_LIVE_EDGE_FOR_QUALITY_INCREASE,
        AdaptiveTrackSelection.DEFAULT_MIN_TIME_BETWEEN_BUFFER_REEVALUTATION_MS,
        Clock.DEFAULT);

    int lowestBitrate = Integer.MAX_VALUE;
    int lowestBitrateTrackIndex = C.INDEX_UNSET;
    for (int i = 0; i < tracks.length; i++) {
      Format format = group.getFormat(tracks[i]);
      if (format.bitrate < lowestBitrate) {
        lowestBitrateTrackIndex = i;
        lowestBitrate = format.bitrate;
      }
      adaptiveTrackSelection.blacklist(tracks[i], BLACKLIST_DURATION);
    }
    if (lowestBitrateTrackIndex != C.INDEX_UNSET) {
      adaptiveTrackSelection.blacklist(tracks[lowestBitrateTrackIndex], 0);
    }
    return adaptiveTrackSelection;
  }

}

现在,在创建DefaultTrackSelector时,您可以传递StartupTrackSelectionFactory并使用它来创建播放器实例。

TrackSelection.Factory trackSelectionFactory = 
          new StartupTrackSelectionFactory(BANDWIDTH_METER);
trackSelector = new DefaultTrackSelector(trackSelectionFactory);
player = ExoPlayerFactory.newSimpleInstance(renderersFactory, trackSelector);

如果你想让你的方法监听onLoadChange事件,你可能希望最初将Long.MAX_VALUE作为黑名单持续时间,然后在调用onLoadChange时将所有索引的持续时间设置为0。

答案 1 :(得分:1)

由于 createTrackSelection 方法从库中移除,我们现在可以直接实现 AdaptiveTrackSelection.Factory() 并覆盖它的 createAdaptiveTrackSelection 方法并使用@marcbaechinger 的代码。 下面是它的 kotlin 版本。

class SmoothTrackSelectionFactory(bandwidthMeter: DefaultBandwidthMeter) : AdaptiveTrackSelection.Factory() {

    // end blacklisting after ten seconds earliest
    private val BLACKLIST_DURATION = (10 * 1000).toLong()

    private var bandwidthMeter: BandwidthMeter = bandwidthMeter

    override fun createAdaptiveTrackSelection(group: TrackGroup, bandwidthMeter: BandwidthMeter, tracks: IntArray, totalFixedTrackBandwidth: Int): AdaptiveTrackSelection {
        val adaptiveTrackSelection = AdaptiveTrackSelection(
                group,
                tracks,
                bandwidthMeter,
                Integer.MAX_VALUE.toLong(),
                AdaptiveTrackSelection.DEFAULT_MIN_DURATION_FOR_QUALITY_INCREASE_MS.toLong(),
                AdaptiveTrackSelection.DEFAULT_MAX_DURATION_FOR_QUALITY_DECREASE_MS.toLong(),
                AdaptiveTrackSelection.DEFAULT_MIN_DURATION_TO_RETAIN_AFTER_DISCARD_MS.toLong(),
                AdaptiveTrackSelection.DEFAULT_BANDWIDTH_FRACTION,
                AdaptiveTrackSelection.DEFAULT_BUFFERED_FRACTION_TO_LIVE_EDGE_FOR_QUALITY_INCREASE,
                AdaptiveTrackSelection.DEFAULT_MIN_TIME_BETWEEN_BUFFER_REEVALUTATION_MS,
                Clock.DEFAULT)
        var lowestBitrate = Int.MAX_VALUE
        var lowestBitrateTrackIndex = C.INDEX_UNSET
        for (i in tracks.indices) {
            val format: Format = group.getFormat(tracks[i])
            if (format.bitrate < lowestBitrate) {
                lowestBitrateTrackIndex = i
                lowestBitrate = format.bitrate
            }
            adaptiveTrackSelection.blacklist(tracks[i], BLACKLIST_DURATION)
        }
        if (lowestBitrateTrackIndex != C.INDEX_UNSET) {
            adaptiveTrackSelection.blacklist(tracks[lowestBitrateTrackIndex], 0)
        }
        return adaptiveTrackSelection
    }
}