LibVLC播放未完整下载视频时如何触发缓冲/错误事件?
解决方案
1. 调整LibVLC初始化参数,降低错误容忍度
修改LibVLC的启动参数,强制触发缓冲或错误事件:
@Composable private fun vlcLib(): LibVLC { val context = LocalContext.current val lib = remember { LibVLC(context, ArrayList<String>().apply { add("--no-drop-late-frames") add("--no-skip-frames") add("--file-caching=1500") // 新增参数 add("--network-caching=1500") // 统一缓存策略,适配分段文件读取 add("--demux-readahead=0") // 关闭预读,避免读取未下载片段 add("--stop-on-skip") // 遇到无法读取的帧时停止播放 add("--error-resilience=0") // 降低错误容忍度,触发错误事件 add(":demux=mp4") // 指定解复用器,增强格式兼容性 if (BuildConfig.DEBUG) { add("-vvv") } }) } DisposableEffect(Unit) { onDispose { lib.release() } } return lib }
2. 监听关键事件并处理播放停滞
在setEventListener中监听Buffering、EncounteredError事件,同时手动检测视频冻结:
LaunchedEffect(Unit) { var lastFrameUpdateTime = System.currentTimeMillis() player.setEventListener { event -> when (event.type) { MediaPlayer.Event.Buffering -> { val progress = event.buffering.toInt() if (progress < 100 && player.isPlaying()) { // 缓冲中,暂停播放并显示提示 player.pause() } else if (progress == 100 && !player.isPlaying()) { // 缓冲完成,恢复播放 player.play() } } MediaPlayer.Event.EncounteredError -> { // 处理媒体读取错误,停止播放并提示 player.stop() } MediaPlayer.Event.TimeChanged -> { val currentTime = System.currentTimeMillis() // 检测视频是否冻结:超过2秒未更新帧且处于播放状态 if (currentTime - lastFrameUpdateTime > 2000 && player.isPlaying()) { player.pause() // 触发自定义的播放停滞提示 } lastFrameUpdateTime = currentTime } } } player.playMediaSource(vlcLib, Uri.fromFile(downloadingMediaFile)) }
3. 修复Media资源管理问题
原playMediaSource方法中Media对象设置后立即释放会导致异常,调整为正确的资源管理方式:
private fun MediaPlayer.playMediaSource(vlcLib: LibVLC, source: Uri) { stop() // 创建Media对象并配置 val media = Media(vlcLib, source).apply { setHWDecoderEnabled(true, false) addOption(":no-mmap") // 禁用内存映射,避免读取空白区域 } // 赋值给播放器 this.media = media // 播放 play() // 在播放器释放时再释放Media // 可在vlcPlayer的DisposableEffect中添加:player.media?.release() }
4. 优化播放器DisposableEffect中的资源释放
确保Media资源被正确释放:
@Composable private fun vlcPlayer(vlcView: VLCVideoLayout, vlcLib: LibVLC): MediaPlayer { val player = remember { MediaPlayer(vlcLib).apply { attachViews(vlcView, null, true, false) } } DisposableEffect(Unit) { onDispose { player.media?.release() // 先释放Media player.release() } } return player }
内容的提问来源于stack exchange,提问作者Arsenius
相关产品推荐
相关产品推荐

