Выбор качества для ExoPlayer 2

В настоящее время я занимаюсь разработкой приложения для просмотра видео в реальном времени. Я выбрал ExoPlayer версии 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() {

}

Пожалуйста, помогите решить эту проблему. большое спасибо.

3 ответа

Решение

Все, чего вы хотите достичь, можно просмотреть в демонстрационном приложении ExoPlayer2. Более конкретно PlayerActivity учебный класс.

Вы также можете проверить эту хорошую статью на эту тему.

Основные моменты, на которые вы хотите обратить внимание, касаются выбора дорожек (через 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, а также Track / TrackGroups чтобы заставить это работать.

Вы могли бы предположительно дословно скопировать демонстрационный код, и он должен работать, но я настоятельно рекомендую уделить время, чтобы понять, что делает каждая часть, и адаптировать ваше решение к вашему варианту использования.

Если бы у меня было больше времени, я бы скомпилировал и запустил его. Но если вы можете получить мой образец, не стесняйтесь редактировать мой пост.

Надеюсь, это поможет:)

Я избегаю пути, как указано выше. Мой способ использует DefaultTrackSelector следующим образом:

trackSelector.setParameters(trackSelector.getParameters()
                          .withMaxVideoBitrate(bitrate)
                          .withMaxVideoSize(width, height));

Я тестировал видео HLS, и, похоже, он работает правильно. Я получаю значения битрейта, ширины и высоты из HlsManifest.

Вы можете скопировать примеры кодов по этой ссылке. ExoPlayer Контроль качества видео.

Примечание. Не забудьте добавить зависимости exoplayer в файл build.gradle.

      implementation 'com.google.android.exoplayer:exoplayer-core:2.16.1'
implementation 'com.google.android.exoplayer:exoplayer-dash:2.16.1'
implementation 'com.google.android.exoplayer:exoplayer-ui:2.16.1'
implementation 'com.google.android.exoplayer:exoplayer:2.16.1'
Другие вопросы по тегам