我正在尝试编写一个应用,其中我需要播放几个视频URL。我正在使用Exo Player播放视频。
Exo Player正在播放视频,但我面临的问题是,exo播放器正在加载视频的某个部分(比如说5秒钟),然后播放它们,一旦exo播放器完成了该部分的播放,它将尝试加载视频的下一部分视频,然后播放视频的该部分。即使互联网速度很好,也会出现此问题。我尝试阅读exo播放器文档和其他stackoverflow帖子,但我无法弄清楚这里出了什么问题。
以下是我的exo播放器单例课程代码:
/**
* Singleton class that manages all video playback in the app. Ensures that only a single stream can be heard at a time
* and reports the current playback status to any interested listeners.
*/
public class VideoWrapper {
private static String TAG = "VideoWrapper";
private int VideoPlaybackState = VideoPlaybackListener.STATE_VIDEO_STOPPED;
// Player that plays the videos.
private SimpleExoPlayer exoPlayer;
// Singleton instance of the class
private static VideoWrapper videoWrapper;
// URL of Current Video Item that is getting played.
private String mCurrentStreamingUrl;
// Handler to take request of video playback in-case there is a playlist is being sent for play.
private Handler handler;
// Add the listener and notify them if required. -- For demo i am not using it but for UI updates and all it will be useful.
private List<VideoPlaybackListener> listeners = new LinkedList<>();
// Tells to which screen we have to go back
private String mPreviousScreenName;
private Context context;
public static VideoWrapper getInstance() {
if (videoWrapper == null) {
videoWrapper = new VideoWrapper();
}
return videoWrapper;
}
// Default constrructor!
private VideoWrapper() {
// Nothing to do.
}
public void setCurrentPreviousScreen(String screen) {
mPreviousScreenName = screen;
}
public void init(Context context) {
try {
this.context = context;
handler = new Handler(context.getMainLooper());
} catch (Exception e) {
// TODO
}
}
public void stopAndReleasePlayer() {
// Stop the player first.
stopVideoStreaming();
// Now release the player and make it null.
if (exoPlayer != null) {
exoPlayer.release();
exoPlayer = null;
}
}
public void addListener(VideoPlaybackListener listener) {
listeners.add(listener);
}
public void removeListener(VideoPlaybackListener listener) {
listeners.remove(listener);
}
public int getVideoPlaybackState() {
return VideoPlaybackState;
}
private SimpleExoPlayer.VideoListener gVideoEventListener = new SimpleExoPlayer.VideoListener() {
@Override
public void onVideoSizeChanged(int width, int height, int unappliedRotationDegrees, float pixelWidthHeightRatio) {
// TODO: Do Something!
}
@Override
public void onRenderedFirstFrame() {
// TODO: Do Something!
}
};
private ExoPlayer.EventListener eventListener = new ExoPlayer.EventListener() {
@Override
public void onTimelineChanged(Timeline timeline, Object manifest) {
// TODO: Do Something!
}
@Override
public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {
// TODO: Do Something!
}
@Override
public void onLoadingChanged(boolean isLoading) {
// TODO: Do Something!
}
@Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
switch (playbackState) {
// playback state handling serially
case ExoPlayer.STATE_IDLE:
// TODO: Do something!
break;
case ExoPlayer.STATE_BUFFERING:
// TODO: Do something!
break;
case ExoPlayer.STATE_READY:
// TODO: Do something!
break;
case ExoPlayer.STATE_ENDED:
// TODO: Do something!
break;
}
}
@Override
public void onPlayerError(ExoPlaybackException error) {
int errorType = error.type;
switch (errorType) {
case ExoPlaybackException.TYPE_RENDERER:
// TODO: Do something!
break;
case ExoPlaybackException.TYPE_SOURCE:
// TODO: Do something!
break;
case ExoPlaybackException.TYPE_UNEXPECTED:
// TODO: Do something!
break;
default:
// TODO: Do something!
break;
}
}
@Override
public void onPositionDiscontinuity() {
// TODO: Do something!
}
};
private boolean canPlayCurrentItem() {
return mCurrentStreamingUrl != null && !TextUtils.isEmpty(mCurrentStreamingUrl);
}
public void stopVideoStreaming() {
if (exoPlayer != null) {
exoPlayer.setPlayWhenReady(false);
}
}
private void restartVideoStreaming() {
if (canPlayCurrentItem()) {
streamCurrentTrack();
}
}
public void startVideoStreaming(String streamUrl) {
// Stop any video if it is playing.
stopVideoStreaming();
VideoPlaybackState = VideoPlaybackListener.STATE_VIDEO_STOPPED;
mCurrentStreamingUrl = streamUrl;
openStreamUrl();
}
private void openStreamUrl() {
Uri uri = Uri.parse(mCurrentStreamingUrl);
TrackSelector trackSelector = new DefaultTrackSelector();
LoadControl loadControl = new DefaultLoadControl();
DefaultBandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
DataSource.Factory dataSourceFactory = buildDataSourceFactory(bandwidthMeter);
// This is the MediaSource representing the media to be played.
HlsMediaSource mediaSource = new HlsMediaSource(uri, dataSourceFactory, handler, new AdaptiveMediaSourceEventListener() {
@Override
public void onLoadStarted(DataSpec dataSpec, int dataType, int trackType, Format trackFormat, int trackSelectionReason, Object trackSelectionData, long mediaStartTimeMs, long mediaEndTimeMs, long elapsedRealtimeMs) {
// TODO: Do something!
}
@Override
public void onLoadCompleted(DataSpec dataSpec, int dataType, int trackType, Format trackFormat, int trackSelectionReason, Object trackSelectionData, long mediaStartTimeMs, long mediaEndTimeMs, long elapsedRealtimeMs, long loadDurationMs, long bytesLoaded) {
// TODO: Do something!
}
@Override
public void onLoadCanceled(DataSpec dataSpec, int dataType, int trackType, Format trackFormat, int trackSelectionReason, Object trackSelectionData, long mediaStartTimeMs, long mediaEndTimeMs, long elapsedRealtimeMs, long loadDurationMs, long bytesLoaded) {
// TODO: Do something!
}
@Override
public void onLoadError(DataSpec dataSpec, int dataType, int trackType, Format trackFormat, int trackSelectionReason, Object trackSelectionData, long mediaStartTimeMs, long mediaEndTimeMs, long elapsedRealtimeMs, long loadDurationMs, long bytesLoaded, IOException error, boolean wasCanceled) {
// TODO: Do something!
}
@Override
public void onUpstreamDiscarded(int trackType, long mediaStartTimeMs, long mediaEndTimeMs) {
// TODO: Do something!
}
@Override
public void onDownstreamFormatChanged(int trackType, Format trackFormat, int trackSelectionReason, Object trackSelectionData, long mediaTimeMs) {
// TODO: Do something!
}
});
exoPlayer.prepare(mediaSource);
streamCurrentTrack();
}
private DataSource.Factory buildDataSourceFactory(DefaultBandwidthMeter bandwidthMeter){
return new DefaultDataSourceFactory(context, bandwidthMeter, buildHttpDataSourceFactory(bandwidthMeter));
}
private HttpDataSource.Factory buildHttpDataSourceFactory(DefaultBandwidthMeter bandwidthMeter){
return new DefaultHttpDataSourceFactory("TiVoPhoenix", bandwidthMeter);
}
public void togglePlayPause() {
if (canPlayCurrentItem()) {
if (VideoPlaybackState == PlaybackListener.STATE_PLAYING) {
stopVideoStreaming();
VideoPlaybackState = PlaybackListener.STATE_PAUSED;
} else {
restartVideoStreaming();
}
}
}
private void streamCurrentTrack() {
VideoPlaybackState = VideoPlaybackListener.STATE_VIDEO_PLAYING;
exoPlayer.setPlayWhenReady(true);
}
public SimpleExoPlayer getPlayer() {
TrackSelector trackSelector = new DefaultTrackSelector();
LoadControl loadControl = new DefaultLoadControl();
// Stop and release the video player before re-creating it.
stopAndReleasePlayer();
exoPlayer = ExoPlayerFactory.newSimpleInstance(context, trackSelector, loadControl);
exoPlayer.addListener(eventListener);
exoPlayer.setVideoListener(gVideoEventListener);
return exoPlayer;
}
}
你们能帮我吗?
答案 0 :(得分:0)
尝试使用此设置进行负载控制:
public class VideoPlayerConfig {
//Minimum Video you want to buffer while Playing
public static final int MIN_BUFFER_DURATION = 2000;
//Max Video you want to buffer during PlayBack
public static final int MAX_BUFFER_DURATION = 5000;
//Min Video you want to buffer before start Playing it
public static final int MIN_PLAYBACK_START_BUFFER = 1500;
//Min video You want to buffer when user resumes video
public static final int MIN_PLAYBACK_RESUME_BUFFER = 2000;
}
LoadControl loadControl = new DefaultLoadControl.Builder()
.setAllocator(new DefaultAllocator(true, 16))
.setBufferDurationsMs(VideoPlayerConfig.MIN_BUFFER_DURATION,
VideoPlayerConfig.MAX_BUFFER_DURATION,
VideoPlayerConfig.MIN_PLAYBACK_START_BUFFER,
VideoPlayerConfig.MIN_PLAYBACK_RESUME_BUFFER)
.setTargetBufferBytes(-1)
.setPrioritizeTimeOverSizeThresholds(true).createDefaultLoadControl();
想法是将最小缓冲区保持为较低,以便视频加载更快。
离题:而且我不知道您为什么要使用单例模式,可能会在应用程序的任何地方获得控制权。使用单例模式时,可以使用对应用程序上下文的弱引用。