Exoplayer 不循环播放视频
Exoplayer not looping the video
我在 android 应用中使用 Exoplayer 来播放视频和音频文件。根据 Exoplayer developer's guide,为了循环 video/audio,这是你必须做的
MediaSource mediaSource = new ExtractorMediaSource(videoUri, ...);
// Loops the video indefinitely.
LoopingMediaSource loopingSource = new LoopingMediaSource(mediaSource);
所以我在 Activity 的 onCreate 方法中这样实现的
BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
TrackSelection.Factory factory = new AdaptiveTrackSelection.Factory(bandwidthMeter);
TrackSelector trackSelector = new DefaultTrackSelector(factory);
simpleExoPlayer = ExoPlayerFactory.newSimpleInstance(this,trackSelector);
simpleExoPlayer.setPlayWhenReady(true);
simpleExoPlayerView.setPlayer(simpleExoPlayer);
// Measures bandwidth during playback. Can be null if not required.
bandwidthMeter2 = new DefaultBandwidthMeter();
// Produces DataSource instances through which media data is loaded.
dataSourceFactory = new DefaultDataSourceFactory(this,
Util.getUserAgent(this, applicationName), bandwidthMeter2);
// Produces Extractor instances for parsing the media data.
extractorsFactory = new DefaultExtractorsFactory();
mediaSource = new ExtractorMediaSource(videoUri,dataSourceFactory, extractorsFactory, null, null);
loopingSource = new LoopingMediaSource(mediaSource);
simpleExoPlayer.prepare(mediaSource);
但是我的视频文件没有循环播放。它只播放一次。
我发现 Exoplayer 开发者指南中遗漏了一些重要信息。创建 LoopingMediaSource
实例后,不应调用 simpleExoPlayer.prepare(mediaSource);
而是调用 simpleExoPlayer.prepare(loopingSource);
。下面是完整的代码
BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
TrackSelection.Factory factory = new AdaptiveTrackSelection.Factory(bandwidthMeter);
TrackSelector trackSelector = new DefaultTrackSelector(factory);
simpleExoPlayer = ExoPlayerFactory.newSimpleInstance(this,trackSelector);
simpleExoPlayer.setPlayWhenReady(true);
simpleExoPlayerView.setPlayer(simpleExoPlayer);
// Measures bandwidth during playback. Can be null if not required.
bandwidthMeter2 = new DefaultBandwidthMeter();
// Produces DataSource instances through which media data is loaded.
dataSourceFactory = new DefaultDataSourceFactory(this,
Util.getUserAgent(this, applicationName), bandwidthMeter2);
// Produces Extractor instances for parsing the media data.
extractorsFactory = new DefaultExtractorsFactory();
MediaSource mediaSource = new ExtractorMediaSource(videoUri,dataSourceFactory, extractorsFactory, null, null);
// Loops the video indefinitely.
LoopingMediaSource loopingSource = new LoopingMediaSource(mediaSource);
simpleExoPlayer.prepare(loopingSource);
player = ExoPlayerFactory.newSimpleInstance(this);
以上代码行使用默认曲目选择器实例化了 ExoPlayer。如果我们不自定义轨道选择器,我们可以避免创建带宽表、轨道选择器。
可以使用 LoopingMediaSource 实现循环。我们必须在 LoopingMediaSouce 构造函数中传递循环计数。如果我们想无限循环播放媒体,最好使用播放器的setRepeatMode()
方法。
new LoopingMediaSource(mediaSource, 3)
附上样本供参考。
<code>
private MediaSource getLoopingMediaSource() {
DefaultDataSourceFactory dataSourceFactory = new DefaultDataSourceFactory(ExoPlayerActivity.this, Util.getUserAgent(ExoPlayerActivity.this, "application-name"));
MediaSource mediaSource = new ExtractorMediaSource.Factory(dataSourceFactory).createMediaSource(Samples.MP4_URI);
LoopingMediaSource loopingMediaSource = new LoopingMediaSource(mediaSource, 3);
return loopingMediaSource;
}
player = ExoPlayerFactory.newSimpleInstance(this);
playerView.setPlayer(player);
player.prepare(getLoopingMediaSource());
player.setPlayWhenReady(true);
</code>
唯一对我有用的解决方案是:
simpleExoPlayer.prepare(mediaSource);
simpleExoPlayer.setPlayWhenReady(true);
simpleExoPlayer.seekTo(0);
exoPlayer.requestFocus();
simpleExoPlayer.addListener(new Player.EventListener() {
@Override
public void onLoadingChanged(boolean isLoading) {
}
@Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
switch (playbackState) {
case Player.STATE_READY:
prog.setVisibility(View.GONE);
simpleExoPlayer.setPlayWhenReady(true);
break;
case Player.STATE_BUFFERING:
prog.setVisibility(View.VISIBLE);
simpleExoPlayer.seekTo(0);
break;
case Player.STATE_IDLE:
simpleExoPlayer.retry();
break;
}
}
});
}
您可以简单地将重复模式设置为 "Repeat_MODE_ONE"。
Kotlin 示例:
val player: SimpleExoPlayer = ExoPlayerFactory.newSimpleInstance(
context,
DefaultRenderersFactory(context),
DefaultTrackSelector(),
DefaultLoadControl()
).apply {
repeatMode = Player.REPEAT_MODE_ONE
}
p.s.The 玩家来自 com.google.android.exoplayer2
只需使用player.setRepeatMode(player.REPEAT_MODE_ONE);
如果你和我一样需要处理Ended事件,可以这样做:
player.addListener(object : Player.Listener {
override fun onPlaybackStateChanged(playbackState: Int) {
if (playbackState == Player.STATE_ENDED) {
...
player.seekTo(0)
player.play()
}
}
})
我在 android 应用中使用 Exoplayer 来播放视频和音频文件。根据 Exoplayer developer's guide,为了循环 video/audio,这是你必须做的
MediaSource mediaSource = new ExtractorMediaSource(videoUri, ...);
// Loops the video indefinitely.
LoopingMediaSource loopingSource = new LoopingMediaSource(mediaSource);
所以我在 Activity 的 onCreate 方法中这样实现的
BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
TrackSelection.Factory factory = new AdaptiveTrackSelection.Factory(bandwidthMeter);
TrackSelector trackSelector = new DefaultTrackSelector(factory);
simpleExoPlayer = ExoPlayerFactory.newSimpleInstance(this,trackSelector);
simpleExoPlayer.setPlayWhenReady(true);
simpleExoPlayerView.setPlayer(simpleExoPlayer);
// Measures bandwidth during playback. Can be null if not required.
bandwidthMeter2 = new DefaultBandwidthMeter();
// Produces DataSource instances through which media data is loaded.
dataSourceFactory = new DefaultDataSourceFactory(this,
Util.getUserAgent(this, applicationName), bandwidthMeter2);
// Produces Extractor instances for parsing the media data.
extractorsFactory = new DefaultExtractorsFactory();
mediaSource = new ExtractorMediaSource(videoUri,dataSourceFactory, extractorsFactory, null, null);
loopingSource = new LoopingMediaSource(mediaSource);
simpleExoPlayer.prepare(mediaSource);
但是我的视频文件没有循环播放。它只播放一次。
我发现 Exoplayer 开发者指南中遗漏了一些重要信息。创建 LoopingMediaSource
实例后,不应调用 simpleExoPlayer.prepare(mediaSource);
而是调用 simpleExoPlayer.prepare(loopingSource);
。下面是完整的代码
BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
TrackSelection.Factory factory = new AdaptiveTrackSelection.Factory(bandwidthMeter);
TrackSelector trackSelector = new DefaultTrackSelector(factory);
simpleExoPlayer = ExoPlayerFactory.newSimpleInstance(this,trackSelector);
simpleExoPlayer.setPlayWhenReady(true);
simpleExoPlayerView.setPlayer(simpleExoPlayer);
// Measures bandwidth during playback. Can be null if not required.
bandwidthMeter2 = new DefaultBandwidthMeter();
// Produces DataSource instances through which media data is loaded.
dataSourceFactory = new DefaultDataSourceFactory(this,
Util.getUserAgent(this, applicationName), bandwidthMeter2);
// Produces Extractor instances for parsing the media data.
extractorsFactory = new DefaultExtractorsFactory();
MediaSource mediaSource = new ExtractorMediaSource(videoUri,dataSourceFactory, extractorsFactory, null, null);
// Loops the video indefinitely.
LoopingMediaSource loopingSource = new LoopingMediaSource(mediaSource);
simpleExoPlayer.prepare(loopingSource);
player = ExoPlayerFactory.newSimpleInstance(this);
以上代码行使用默认曲目选择器实例化了 ExoPlayer。如果我们不自定义轨道选择器,我们可以避免创建带宽表、轨道选择器。
可以使用 LoopingMediaSource 实现循环。我们必须在 LoopingMediaSouce 构造函数中传递循环计数。如果我们想无限循环播放媒体,最好使用播放器的setRepeatMode()
方法。
new LoopingMediaSource(mediaSource, 3)
附上样本供参考。
<code>
private MediaSource getLoopingMediaSource() {
DefaultDataSourceFactory dataSourceFactory = new DefaultDataSourceFactory(ExoPlayerActivity.this, Util.getUserAgent(ExoPlayerActivity.this, "application-name"));
MediaSource mediaSource = new ExtractorMediaSource.Factory(dataSourceFactory).createMediaSource(Samples.MP4_URI);
LoopingMediaSource loopingMediaSource = new LoopingMediaSource(mediaSource, 3);
return loopingMediaSource;
}
player = ExoPlayerFactory.newSimpleInstance(this);
playerView.setPlayer(player);
player.prepare(getLoopingMediaSource());
player.setPlayWhenReady(true);
</code>
唯一对我有用的解决方案是:
simpleExoPlayer.prepare(mediaSource);
simpleExoPlayer.setPlayWhenReady(true);
simpleExoPlayer.seekTo(0);
exoPlayer.requestFocus();
simpleExoPlayer.addListener(new Player.EventListener() {
@Override
public void onLoadingChanged(boolean isLoading) {
}
@Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
switch (playbackState) {
case Player.STATE_READY:
prog.setVisibility(View.GONE);
simpleExoPlayer.setPlayWhenReady(true);
break;
case Player.STATE_BUFFERING:
prog.setVisibility(View.VISIBLE);
simpleExoPlayer.seekTo(0);
break;
case Player.STATE_IDLE:
simpleExoPlayer.retry();
break;
}
}
});
}
您可以简单地将重复模式设置为 "Repeat_MODE_ONE"。
Kotlin 示例:
val player: SimpleExoPlayer = ExoPlayerFactory.newSimpleInstance(
context,
DefaultRenderersFactory(context),
DefaultTrackSelector(),
DefaultLoadControl()
).apply {
repeatMode = Player.REPEAT_MODE_ONE
}
p.s.The 玩家来自 com.google.android.exoplayer2
只需使用player.setRepeatMode(player.REPEAT_MODE_ONE);
如果你和我一样需要处理Ended事件,可以这样做:
player.addListener(object : Player.Listener {
override fun onPlaybackStateChanged(playbackState: Int) {
if (playbackState == Player.STATE_ENDED) {
...
player.seekTo(0)
player.play()
}
}
})