1

VideoView을 사용하여 URL에서 동영상을 재생하는 Android TV 앱에서 작업하고 있습니다. 비디오가 일시 정지 된 후 다시 시작될 때마다 먼저 비디오를 미리 다운로드하는 데 시간이 걸립니다 (진행률 막대가 나타나는 동안 몇 초간). 목표는 재생 중에 비디오를 버퍼링하여 일시 중지 한 후 다시 시작할 때 지연없이 즉시 프리 버퍼 된 상태에서 다시 시작하는 것입니다. 또한 videoView.resume() 메서드를 시도했지만 도움이되지 않습니다. 그 일을 할 수있는 방법이 있습니까? 아니면 제가 잘못하고있는 것입니까? 여기 Android VideoView 버퍼링

가 재생되는 코드입니다/비디오 다시 시작 : 나는 단지 ExoPlayer를 사용하여 VideoView와이를 달성 할 수있는 방법을 찾을 수 없습니다했습니다 불행하게도

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

가 [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); } 

그리고 Player 구현 : 여기에

내가 ExoPlayer를 사용하여 결국 한 최종 코드 guide/topics/media/exoplayer.html)? more : http://google.github.io/ExoPlayer/guide.html#pros-and-cons – pskink

+0

@pskink 아니요, 아닙니다. 사용하는 데 변경해야 할 코드가 많으므로'VideoView '로이 코드를 작성하고 싶습니다. 현재이 문제가 유일한 문제이며 다른 모든 작업이 가능합니다. –

+0

'VideoView'로 스트림을 부드럽게 할 수 없다면 나쁜 소식입니다. –

답변

1

을, 감사 권리를 @pskink하기 방향. API가 mp4 비디오를 반환하기 때문에 ExtractorMediaSource을 사용했습니다. 여러 형식을 지원하는 완전한 데모 예제는 ExoPlayer GitHub page에서 찾을 수 있습니다. https://developer.android.com/

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); 
    } 
}