ExoPlayer播放直播URL时挂起、崩溃问题如何排查解决
ExoPlayer 直播流场景偶现挂起、崩溃修复方案
当前实现没有针对直播流场景做适配,默认配置在弱网、资源加载超时、字幕资源异常时很容易触发播放器线程阻塞、ANR甚至崩溃,和预判的超时原因吻合。
现有问题代码
Uri assetSrtUri = Uri.parse(vvtFilePath); MediaItem.SubtitleConfiguration subtitle = new MediaItem.SubtitleConfiguration.Builder(assetSrtUri) .setMimeType(MimeTypes.TEXT_VTT) .setLanguage("en") .setSelectionFlags(C.SELECTION_FLAG_DEFAULT) .build(); MediaItem mediaItem = new MediaItem.Builder() .setUri(uri) .setSubtitleConfigurations(ImmutableList.of(subtitle)) .build(); player.setMediaItem(mediaItem); player.prepare();
异常截图

核心问题点
- 默认LoadControl的缓冲参数针对点播场景设计,直播流长连接无数据时会持续等待,直接触发挂起
- 默认数据源网络超时时间过长,主直播流、字幕资源加载阻塞时会卡住播放器内部调度
- 未配置播放器错误监听,异常发生时没有兜底处理逻辑,错误累积最终触发崩溃
修复实现
- 引入OkHttp数据源扩展,配置合理的网络超时参数,替换默认数据源:
// 按需调整超时时间,直播场景不建议超过15s OkHttpClient okHttpClient = new OkHttpClient.Builder() .connectTimeout(10, TimeUnit.SECONDS) .readTimeout(10, TimeUnit.SECONDS) .writeTimeout(10, TimeUnit.SECONDS) .build(); OkHttpDataSource.Factory networkFactory = new OkHttpDataSource.Factory(okHttpClient); DefaultDataSource.Factory dataSourceFactory = new DefaultDataSource.Factory(getApplicationContext(), networkFactory); - 针对直播流自定义缓冲控制参数,避免无意义的长时间缓冲等待:
DefaultLoadControl liveLoadControl = new DefaultLoadControl.Builder() .setBufferDurationsMs( 2000, // 最小缓冲时长2s 5000, // 最大缓冲时长5s 1000, // 初始缓冲1s即可起播 1000 // 卡顿时缓冲1s就尝试恢复播放 ) .setPrioritizeTimeOverSizeThresholds(true) .build(); - 初始化播放器时传入自定义配置,添加错误监听做兜底处理:
SimpleExoPlayer player = new SimpleExoPlayer.Builder(getApplicationContext()) .setDataSourceFactory(dataSourceFactory) .setLoadControl(liveLoadControl) .build(); // 监听播放器错误,异常时及时释放阻塞,按需做重试逻辑 player.addListener(new Player.Listener() { @Override public void onPlayerError(PlaybackException error) { player.stop(); // 网络类错误可触发有限次重试,其他错误直接上报做降级处理 if (error.errorCode == PlaybackException.ERROR_CODE_IO_NETWORK_CONNECTION_TIMEOUT || error.errorCode == PlaybackException.ERROR_CODE_IO_NETWORK_CONNECTION_FAILED) { // 实现自定义重试逻辑,注意加重试次数限制,避免无限重试 } } }); // 原有MediaItem构建逻辑可保留,注意提前校验字幕资源地址的可达性 Uri assetSrtUri = Uri.parse(vvtFilePath); MediaItem.SubtitleConfiguration subtitle = new MediaItem.SubtitleConfiguration.Builder(assetSrtUri) .setMimeType(MimeTypes.TEXT_VTT) .setLanguage("en") .setSelectionFlags(C.SELECTION_FLAG_DEFAULT) .build(); MediaItem mediaItem = new MediaItem.Builder() .setUri(uri) .setSubtitleConfigurations(ImmutableList.of(subtitle)) .build(); player.setMediaItem(mediaItem); player.prepare();
额外注意:如果使用HLS/DASH等协议的直播流,可以在构建MediaItem时通过
setLiveConfiguration配置直播最大偏移容忍度,进一步降低挂起概率;如果字幕是远程资源,需要确认服务端支持Range请求,避免字幕加载失败连带触发播放器异常。
内容的提问来源于stack exchange,提问作者Hemant Bharti
相关产品推荐
相关产品推荐

