当前,我有一台服务器,该服务器流传输四个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)+"");
}
}
}
}
}
只需为我提供1种视频格式和1种音频格式。
我当前的解决方法是在后台准备另一个ExoPlayer
实例,在准备工作完成后用当前实例替换当前正在运行的实例,然后释放旧实例。这在某种程度上减少了MediaSources
之间的延迟,但是并不能像Youtube那样实现无缝的分辨率更改。
我应该实现自己的TrackSelector
并将所有4个源打包到其中,还是实现另一个可以处理所有4个源的MediaSource,或者我应该告诉维护流的同事切换到一个RTMP MediaSource
,带有某种清单,其中列出了AdaptiveTrackSelection
可以在它们之间切换的所有分辨率?
答案 0 :(得分:0)
自适应比特率流传输旨在允许在不同的比特率流之间轻松切换,但是它要求对流进行分段,并且播放器逐段下载视频。
通过这种方式,播放器可以根据当前网络条件(以及设备的显示尺寸和t类型)来决定为下一个段选择哪个比特率。除了不同的比特率和质量,播放器还可以无缝地从一种比特率转换到另一种比特率。
有关更多信息,请参见此处:https://stackoverflow.com/a/42365034/334402
以上所有内容均取决于支持此分段和不同比特率流的传输协议。今天最常见的是HLS和MPEG-DASH。
支持我认为正在寻找的最简单方法是为您的同事提供流,以使用HLS和/或DASH来提供流。
请注意,目前,HLS和DASH都是必需的,因为Apple设备需要HLS,而其他设备往往默认为DASH。传统上,HLS使用TS作为分段中视频的容器,而DASH使用分段的MP4,但是现在两者都可以使用CMAF,后者实质上是分段的MP4。
因此,从理论上讲,现在可以将一套比特率视频用于HLS和DASH-实际上,这将取决于您的内容是否已加密,因为HLS和Apple使用了一种加密模式,而其他人则使用了其他加密模式。过去。现在,这种情况也在发生变化,但是在所有设备都支持新方法之前,还需要花费一些时间,因为所有设备都可以支持相同的加密模式,因此,如果对流进行加密,那么这会增加复杂性。