目前,我有一个服务器可以传输四个RTMP MediaSource
,一个有720p视频源,一个有360p视频源,一个有180p视频源,还有一个只有音频源。如果我想要切换分辨率,我必须停止ExoPlayer
实例,准备我想要切换到的另一首曲目,然后播放。
我用来准备ExoPlayer
实例的代码如下:
TrackSelection.Factory adaptiveTrackSelectionFactory = new AdaptiveTrackSelection.Factory(bandwidthMeter);
TrackSelector trackSelector = new DefaultTrackSelector(adaptiveTrackSelectionFactory);
RtmpDataSourceFactory rtmpDataSourceFactory = new RtmpDataSourceFactory(bandwidthMeter);
ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory();
factory = new AVControlExtractorMediaSource.Factory(rtmpDataSourceFactory);
factory.setExtractorsFactory(extractorsFactory);
createSource();
//noinspection deprecation
mPlayer = ExoPlayerFactory.newSimpleInstance(mActivity, trackSelector, new DefaultLoadControl(
new DefaultAllocator(true, C.DEFAULT_BUFFER_SEGMENT_SIZE),
1000, // min buffer
2000, // max buffer
1000, // playback
1000, //playback after rebuffer
DefaultLoadControl.DEFAULT_TARGET_BUFFER_BYTES,
true
));
vwExoPlayer.setPlayer(mPlayer);
mPlayer.addAnalyticsListener(mAnalyticsListener);
其中createSource()
为:
private void createSource() {
factory.setTrackPlaybackFlag(AVControlExtractorMediaSource.PLAYBACK_BOTH_AV);
mMediaSource180 = factory.createMediaSource(Uri.parse(API.GAME_VIDEO_STREAM_URL_180()));
mMediaSource180.addEventListener(getHandler(), new MSourceDebuggerListener("GameMediaSource180"));
mMediaSource360 = factory.createMediaSource(Uri.parse(API.GAME_VIDEO_STREAM_URL_360()));
mMediaSource360.addEventListener(getHandler(), new MSourceDebuggerListener("GameMediaSource360"));
mMediaSource720 = factory.createMediaSource(Uri.parse(API.GAME_VIDEO_STREAM_URL_720()));
mMediaSource720.addEventListener(getHandler(), new MSourceDebuggerListener("GameMediaSource720"));
factory.setTrackPlaybackFlag(AVControlExtractorMediaSource.PLAYBACK_AUDIO_ONLY);
mMediaSourceAudio = factory.createMediaSource(Uri.parse(API.GAME_AUDIO_STREAM_URL()));
mMediaSourceAudio.addEventListener(getHandler(), new MSourceDebuggerListener("GameMediaSourceAudio"));
}
private void releaseSource() {
mMediaSource180.releaseSource(null);
mMediaSource360.releaseSource(null);
mMediaSource720.releaseSource(null);
mMediaSourceAudio.releaseSource(null);
}
我目前用来在这些MediaSources
之间切换的代码是:
private void changeTrack(MediaSource source) {
if (currentMediaSource == source) return;
try {
this.currentMediaSource = source;
mPlayer.stop(true);
mPlayer.prepare(source, true, true);
mPlayer.setPlayWhenReady(true);
if (source == mMediaSourceAudio) {
if (!audioOnly) {
try {
TransitionManager.beginDelayedTransition(rootView);
} catch (Exception ignored) {
}
layAudioOnly.setVisibility(View.VISIBLE);
vwExoPlayer.setVisibility(View.INVISIBLE);
audioOnly = true;
try {
GameQnAFragment fragment = findFragment(GameQnAFragment.class);
if (fragment != null) {
fragment.signAudioOnly();
}
} catch (Exception e) {
Trace.e(e);
}
try {
GamePollingFragment fragment = findFragment(GamePollingFragment.class);
if (fragment != null) {
fragment.signAudioOnly();
}
} catch (Exception e) {
Trace.e(e);
}
}
} else {
if (audioOnly) {
TransitionManager.beginDelayedTransition(rootView);
layAudioOnly.setVisibility(View.GONE);
vwExoPlayer.setVisibility(View.VISIBLE);
audioOnly = false;
}
}
} catch (Exception ignore) {
}
}
我想实现这些MediaSource
之间的无缝切换,这样我就不需要停下来重新准备了,但是ExoPlayer似乎不支持这个功能。
此外,使用以下代码记录每个MediaSource
结构:
MappingTrackSelector.MappedTrackInfo info = ((DefaultTrackSelector)trackSelector).getCurrentMappedTrackInfo();
if(info != null) {
for (int i = 0; i < info.getRendererCount(); i++) {
TrackGroupArray trackGroups = info.getTrackGroups(i);
if (trackGroups.length != 0) {
for(int j = 0; j < trackGroups.length; j++) {
TrackGroup tg = trackGroups.get(j);
for(int k = 0; k < tg.length; k++) {
Log.i("track_info_"+i+"-"+j+"-"+k, tg.getFormat(k)+"");
}
}
}
}
}
只是给我一种视频格式和一种音频格式。
我目前的解决方法是在后台准备另一个ExoPlayer
实例,在准备完成后将当前运行的实例替换为该实例,然后释放旧实例。这在一定程度上减少了MediaSources
之间的延迟,但无法实现像Youtube那样的无缝分辨率转换。
我是否应该实现自己的TrackSelector
并将所有4个源打包到其中,我是应该实现另一个处理所有4个源的MediaSource,还是应该只告诉维护流的同事切换到一个RTMP MediaSource
,并列出AdaptiveTrackSelection
可以在它们之间切换的所有可用分辨率?
发布于 2018-11-02 20:01:05
自适应比特率流旨在允许在不同比特率流之间轻松切换,但它需要对流进行分段,并要求播放器逐段下载视频。
以这种方式,播放器可以根据当前网络条件(以及设备显示大小和T类型)来决定为下一段选择哪种比特率。除了不同的比特率和质量之外,播放器还能够以这种方式从一个比特率无缝移动到另一个比特率。
更多信息请看这里:https://stackoverflow.com/a/42365034/334402
所有这些都依赖于支持这种分段和不同比特率流的传送协议。目前最常见的是HLS和MPEG-DASH。
要支持我认为你正在寻找的东西,最简单的方法是让你的同事使用HLS和/或DASH来提供流。
请注意,目前,HLS和DASH都是必需的,因为苹果设备需要HLS,而其他设备倾向于默认使用DASH。传统上,HLS使用TS作为片段中的视频容器,DASH使用碎片MP4,但现在两者都使用MP4,这本质上是碎片CMAF。
所以从理论上讲,单个码率的视频现在可以用于HLS和DASH实际上这将取决于你的内容是否加密,就像HLS和苹果过去使用一种加密模式,而其他所有人使用另一种加密模式一样。这种情况现在也在改变,但在所有设备支持新方法之前需要时间,所有设备都可以支持相同的加密模式,所以如果你的流是加密的,这在目前是一个额外的复杂性。
https://stackoverflow.com/questions/53095184
复制相似问题