带起始曲目的短跑自适应播放,如何?
Dash adaptive playback with starting tracks, How to?
我有 3 种方式在我的应用程序中播放自适应破折号视频:
- 固定视频和音频轨道
- 自适应视频和音频轨道
- 自适应视频和音频轨道(带起始轨道)
前两种方法非常有效,但是第三种方法表现得很奇怪。
我所做的是首先在 'onTracksChanged' 方法上设置起始曲目。一旦播放器调用 onLoadingChanged(false) 方法,我想删除起始轨道的 selection 并让播放器 select 最佳轨道。为了删除 selected,我调用了 trackSelector.clearSelectionOverrides(),但这完全删除了缓冲区,视频停止并开始在最佳轨道中缓冲。
我想要实现的行为如下:
select startt tracks (假设是 144p) -> 加载第一个块 -> 删除 144p 的 selection -> 继续以 144p 播放剩余的缓冲区并开始以最佳方式加载同时跟踪。
如何实现?
您可以使用 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。
由于 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
}
}
我有 3 种方式在我的应用程序中播放自适应破折号视频:
- 固定视频和音频轨道
- 自适应视频和音频轨道
- 自适应视频和音频轨道(带起始轨道)
前两种方法非常有效,但是第三种方法表现得很奇怪。
我所做的是首先在 'onTracksChanged' 方法上设置起始曲目。一旦播放器调用 onLoadingChanged(false) 方法,我想删除起始轨道的 selection 并让播放器 select 最佳轨道。为了删除 selected,我调用了 trackSelector.clearSelectionOverrides(),但这完全删除了缓冲区,视频停止并开始在最佳轨道中缓冲。
我想要实现的行为如下:
select startt tracks (假设是 144p) -> 加载第一个块 -> 删除 144p 的 selection -> 继续以 144p 播放剩余的缓冲区并开始以最佳方式加载同时跟踪。
如何实现?
您可以使用 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。
由于 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
}
}