exoplayer - 为什么 Exoplayer 在带宽变化时不切换 HLS 轨道

标签 exoplayer exoplayer2.x

我有这个简单的 .m3u8 文件

#EXTM3U
#EXT-X-VERSION:5

#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="audio",NAME="English stereo",LANGUAGE="en"

#EXT-X-STREAM-INF:BANDWIDTH=1728000,CODECS="avc1.42c00d,mp4a.40.2",RESOLUTION=640x360,AUDIO="audio"
https://bitdash-a.akamaihd.net/content/MI201109210084_1/m3u8s/f08e80da-bf1d-4e3d-8899-f0f6155f6efa_video_360_800000.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=628000,CODECS="avc1.42c00d,mp4a.40.2",RESOLUTION=320x180,AUDIO="audio"
https://bitdash-a.akamaihd.net/content/MI201109210084_1/m3u8s/f08e80da-bf1d-4e3d-8899-f0f6155f6efa_video_180_250000.m3u8

使用 simpleExoplayer 我像这样加载这个流:

// 1. Create a default TrackSelector
Handler mainHandler = new Handler();
BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
TrackSelection.Factory videoTrackSelectionFactory =
    new AdaptiveTrackSelection.Factory(bandwidthMeter);
TrackSelector trackSelector =
    new DefaultTrackSelector(videoTrackSelectionFactory);

// 2. Create the player
SimpleExoPlayer player =
    ExoPlayerFactory.newSimpleInstance(context, trackSelector);

// Produces DataSource instances through which media data is loaded.
DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(context,
    Util.getUserAgent(context, "yourApplicationName"), bandwidthMeter);
// This is the MediaSource representing the media to be played.
MediaSource videoSource = new HlsMediaSource.Factory(dataSourceFactory)
    .createMediaSource(mp4VideoUri);
// Prepare the player with the source.
player.prepare(videoSource);
player.setPlayWhenReady(true);

但即使在高速 WIFI 互联网上,它也始终会选择分辨率为 320x180 的第二条轨道,并且永远不会切换到分辨率为 640x360 的更高轨道。

如果我用 maxInt 替换 DEFAULT_MAX_INITIAL_BITRATE 那么它会正确选择第一个音轨 (640x360) 但如果在播放过程中我切断了 wifi 让手机只使用低 3G 连接,那么它永远不会切换到第二首轨道 (320x180) 每次播放都会卡住

同时检查 MediaCodecUtil.getDecoderInfo("video/avc", false).adaptive 并返回 TRUE

我做错了什么? hls 在 simpleExoPlayer 中是否正常工作?

最佳答案

DefaultBandwidthMeter 是测量网络容量的组件。 DefaultBandwidthMeter 实现了 BandwidthMeterTransferListener 接口(interface)。

您应该只使用 DefaultBandwidthMeter 的一个实例并将其传递给两者,AdaptiveTrackSelection.Factory(作为 BandwidthMeter)和 DefaultDataSourceFactory(作为 TransferListener)。这样,在数据源中完成的计量会在轨道选择器中生效。

在您传递给 AdaptiveTrackSelection 的实例上方的代码中,Factory 不知道计量的是什么,根据您的描述,这显然不起作用。

另请注意,如果您创建一个新的 DefaultBandwidthMeter 实例,那么到目前为止完成的计量将会丢失。因此,您可能希望将 DefaultBandwidthMeter 作为静态变量等,以保留早期播放的计量。

TrackSelection.Factory videoTrackSelectionFactory =
    new AdaptiveTrackSelection.Factory(DEFAULT_BANDWIDTH_METER);
TrackSelector trackSelector =
    new DefaultTrackSelector(videoTrackSelectionFactory);

DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(context,
    Util.getUserAgent(context, "yourApplicationName"), DEFAULT_BANDWIDTH_METER);

另见 how the PlayerActivity of the demo application does it .

关于exoplayer - 为什么 Exoplayer 在带宽变化时不切换 HLS 轨道,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48527829/

相关文章:

Android - 具有音频焦点的 SimpleExoPlayer

android - 如何在android ExoPlayer中显示字幕

支持 MPEG-DASH 的 Android 媒体播放器

android - Exoplayer 无法捕获错误 - 输入不以 #EXTM3U header 开头

android - 我如何让 ExoPlayer 在我的 Activity 的 onStart() 方法中恢复视频?

android - 从 GL_TEXTURE_EXTERNAL_OES 读取到 GL_TEXTURE_2D 存在性能问题和故障

android - Exoplayer 源错误

android - 如何以图片模式在我的 Activity 图片中播放youtube视频

android - 如何重新定位 Jetpack-media3/exoplayer 控制按钮?

android - 不推荐使用 SimpleExoPlayer.Builder(this).build()