1

Je travaille sur l'application Android TV qui utilise VideoView pour lire la vidéo à partir de l'URL. Chaque fois que la vidéo est mise en pause puis reprise, il faut d'abord la télécharger au préalable (quelques secondes pendant lesquelles la barre de progression apparaît). Le but est de mettre en mémoire tampon la vidéo pendant la lecture de sorte que lorsque je la fais une pause puis la reprenne - elle reprend immédiatement l'état pré-tamponné. J'ai également essayé la méthode videoView.resume(), mais cela n'aide pas non plus. Y a-t-il un moyen de le faire ou est-ce que je fais quelque chose de mal?Android VideoView mise en mémoire tampon

Voici le code qui joue/reprend la vidéo:

public void onFragmentPlayPause(final Video video, 
            final VideoQuality quality, 
            final int position, 
            final Boolean play) { 
     stopSeeking(); 

     videoView.setVideoPath(video.videoUrl(quality)); 

     if (position == 0 || playbackState == LeanbackPlaybackState.IDLE) { 
      setupCallbacks(); 
      playbackState = LeanbackPlaybackState.IDLE; 
     } 

     if (play && playbackState != LeanbackPlaybackState.PLAYING) { 
      progressBar.setVisibility(View.VISIBLE); 
      playbackState = LeanbackPlaybackState.PLAYING; 
      if (position > 0) { 
       videoView.seekTo(position); 
       videoView.start(); 
      } 
      playbackFragment.startProgressObservation(progressFlowable()); 
     } else { 
      playbackState = LeanbackPlaybackState.PAUSED; 
      videoView.pause(); 
      playbackFragment.stopProgressObservation(); 
     } 

     updatePlaybackState(position); 
     updateMetadata(video); 
    } 
+0

essayé [ExoPlayer] (https://developer.android.com/ guide/topics/media/exoplayer.html)? plus ici: http://google.github.io/ExoPlayer/guide.html#pros-and-cons – pskink

+0

@pskink non, je n'ai pas. Il y a beaucoup de code qui doit être changé si je l'utilise, donc je voudrais réaliser cela avec 'VideoView'. Actuellement, c'est le seul problème, tout le reste fonctionne. –

+0

C'est une mauvaise nouvelle s'il n'y a aucun moyen de fluidifier le flux avec 'VideoView'. –

Répondre

1

Malheureusement, je l'ai n'a pas trouvé le moyen d'y parvenir avec VideoView, en utilisant uniquement ExoPlayer, grâce à @pskink le droit direction. L'API renvoyait des vidéos mp4, j'ai donc utilisé ExtractorMediaSource. L'exemple de démonstration complet avec support de plusieurs formats peut être trouvé sur ExoPlayer GitHub page.

Voici le code final j'ai fini avec l'aide ExoPlayer:

private void playPause(final Video video, final int position, final Boolean play) { 
     if (position == 0 || playbackState == LeanbackPlaybackState.IDLE) { 
      setupCallbacks(); 
      playbackState = LeanbackPlaybackState.IDLE; 
     } 

     if (play && playbackState != LeanbackPlaybackState.PLAYING) { 
      progressBar.setVisibility(View.VISIBLE); 
      playbackState = LeanbackPlaybackState.PLAYING; 
      player.start(); 
      playbackFragment.startProgressObservation(progressFlowable()); 
     } else { 
      playbackState = LeanbackPlaybackState.PAUSED; 
      player.pause(); 
      playbackFragment.stopProgressObservation(); 
     } 

     updatePlaybackState(position); 
     updateMetadata(video); 
    } 

Et Player mise en œuvre:

public class Player implements MediaController.MediaPlayerControl, ExoPlayer.EventListener { 

    private static final DefaultBandwidthMeter BANDWIDTH_METER = new DefaultBandwidthMeter(); 

    private final SimpleExoPlayer exoPlayer; 
    private final Context context; 

    private OnErrorListener onErrorListener; 
    private OnPreparedListener onPreparedListener; 
    private OnCompletionListener onCompletionListener; 

    private String url; 

    public interface OnErrorListener { 
     void onError(final Exception e); 
    } 

    public interface OnPreparedListener { 
     void onPrepared(); 
    } 

    public interface OnCompletionListener { 
     void onComplete(); 
    } 

    public Player(final Context context) { 
     this.context = context; 

     final @SimpleExoPlayer.ExtensionRendererMode int extensionRendererMode = 
       SimpleExoPlayer.EXTENSION_RENDERER_MODE_OFF; 
     final TrackSelection.Factory videoTrackSelectionFactory = 
       new AdaptiveTrackSelection.Factory(BANDWIDTH_METER); 
     this.exoPlayer = ExoPlayerFactory.newSimpleInstance(
       context, 
       new DefaultTrackSelector(videoTrackSelectionFactory), 
       new DefaultLoadControl(), 
       null, 
       extensionRendererMode 
     ); 
     this.exoPlayer.addListener(this); 
    } 

    @Override 
    public boolean canPause() { 
     return true; 
    } 

    @Override 
    public boolean canSeekBackward() { 
     return true; 
    } 

    @Override 
    public boolean canSeekForward() { 
     return true; 
    } 

    @Override 
    public int getAudioSessionId() { 
     throw new UnsupportedOperationException(); 
    } 

    @Override 
    public int getBufferPercentage() { 
     return exoPlayer.getBufferedPercentage(); 
    } 

    @Override 
    public int getCurrentPosition() { 
     return exoPlayer.getDuration() == com.google.android.exoplayer2.C.TIME_UNSET ? 0 
       : (int) exoPlayer.getCurrentPosition(); 
    } 

    @Override 
    public int getDuration() { 
     return exoPlayer.getDuration() == com.google.android.exoplayer2.C.TIME_UNSET ? 0 
       : (int) exoPlayer.getDuration(); 
    } 

    @Override 
    public boolean isPlaying() { 
     return exoPlayer.getPlayWhenReady(); 
    } 

    @Override 
    public void start() { 
     exoPlayer.setPlayWhenReady(true); 
    } 

    @Override 
    public void pause() { 
     exoPlayer.setPlayWhenReady(false); 
    } 

    public void stop() { 
     exoPlayer.seekTo(0); 
     pause(); 
    } 

    public void setOnErrorListener(final OnErrorListener onErrorListener) { 
     this.onErrorListener = onErrorListener; 
    } 

    public void setOnPreparedListener(final OnPreparedListener onPreparedListener) { 
     this.onPreparedListener = onPreparedListener; 
    } 

    public void setOnCompletionListener(final OnCompletionListener onCompletionListener) { 
     this.onCompletionListener = onCompletionListener; 
    } 

    public void setVolume(final float volume) { 
     exoPlayer.setVolume(volume); 
    } 

    public void release() { 
     exoPlayer.release(); 
    } 

    public void updateUrl(final String url) { 
     this.url = url; 
     exoPlayer.prepare(buildMediaSource(Uri.parse(url))); 
    } 

    public SimpleExoPlayer exoPlayer() { 
     return exoPlayer; 
    } 

    @Override 
    public void seekTo(final int timeMillis) { 
     exoPlayer.seekTo(timeMillis); 
    } 

    @Override 
    public void onTimelineChanged(final Timeline timeline, final Object manifest) { 
    } 

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

    @Override 
    public void onLoadingChanged(final boolean isLoading) { 
    } 

    @Override 
    public void onPlayerStateChanged(final boolean playWhenReady, final int playbackState) { 
     if (playbackState == ExoPlayer.STATE_READY) { 
      onPreparedListener.onPrepared(); 
     } 
     if (playbackState == ExoPlayer.STATE_ENDED) { 
      onCompletionListener.onComplete(); 
     } 
    } 

    @Override 
    public void onPlayerError(final ExoPlaybackException error) { 
     onErrorListener.onError(error); 
    } 

    @Override 
    public void onPositionDiscontinuity() { 
    } 

    public String url() { 
     return url; 
    } 

    private MediaSource buildMediaSource(final Uri uri) { 
     return new ExtractorMediaSource(uri, buildDataSourceFactory(true), new DefaultExtractorsFactory(), 
       null, null); 
    } 

    private DataSource.Factory buildDataSourceFactory(final DefaultBandwidthMeter bandwidthMeter) { 
     return new DefaultDataSourceFactory(context, bandwidthMeter, 
       buildHttpDataSourceFactory(bandwidthMeter)); 
    } 

    private HttpDataSource.Factory buildHttpDataSourceFactory(final DefaultBandwidthMeter bandwidthMeter) { 
     return new DefaultHttpDataSourceFactory(Util.getUserAgent(context, Application.TAG), bandwidthMeter); 
    } 

    private DataSource.Factory buildDataSourceFactory(final boolean useBandwidthMeter) { 
     return buildDataSourceFactory(useBandwidthMeter ? BANDWIDTH_METER : null); 
    } 
}