如何在下载视频前获取ExoPlayer视频参数,调整RecyclerView中播放器尺寸?
在ExoPlayer中预加载元数据获取视频宽高比(适配RecyclerView)
要在下载完整视频前获取视频宽高/宽高比,核心是利用ExoPlayer加载媒体元数据的机制——它会先请求视频的头部信息而非完整内容,通过监听轨道或元数据变化回调就能拿到所需参数,进而调整RecyclerView中PlayerView的尺寸。
具体实现步骤
初始化ExoPlayer并添加监听器
在RecyclerView的ViewHolder中,初始化播放器后添加Player.Listener,通过onTracksChanged回调获取最准确的视频轨道参数(比元数据更可靠):val player = ExoPlayer.Builder(itemView.context).build() player.addListener(object : Player.Listener { override fun onTracksChanged(tracks: Tracks) { super.onTracksChanged(tracks) // 筛选出视频轨道 val videoTrackGroups = tracks.groups.filter { it.type == C.TRACK_TYPE_VIDEO } if (videoTrackGroups.isNotEmpty()) { val videoFormat = videoTrackGroups[0].getFormat(0) val videoWidth = videoFormat.width val videoHeight = videoFormat.height if (videoWidth > 0 && videoHeight > 0) { // 计算宽高比并调整PlayerView布局 val aspectRatio = videoWidth.toFloat() / videoHeight.toFloat() val layoutParams = playerView.layoutParams layoutParams.height = (playerView.width / aspectRatio).toInt() playerView.layoutParams = layoutParams } } } })加载媒体元数据而非完整视频
设置MediaItem后调用prepare(),ExoPlayer会自动加载元数据(远程视频仅请求头部信息),不会下载完整内容:val mediaItem = MediaItem.fromUri(videoUrl) player.setMediaItem(mediaItem) player.prepare()处理RecyclerView复用问题
在ViewHolder的回收回调中,务必移除监听器并释放播放器资源,避免内存泄漏和重复回调:override fun onViewRecycled(holder: VideoViewHolder) { super.onViewRecycled(holder) holder.player.removeListener(holder.playerListener) holder.player.release() }
注意事项
- 优先使用
onTracksChanged回调的轨道信息,因为MediaMetadata中的宽高可能存在缺失或不准确的情况。 - 如果需要适配横竖屏切换,可在回调中重新计算宽高比并更新布局。
- 对于本地视频,ExoPlayer会直接读取文件头部元数据,效率更高。
内容的提问来源于stack exchange,提问作者Hamza Sharaf
相关产品推荐
相关产品推荐

