Flutter audio_service插件弱网下播放进度条异常移动问题求助
解决方案
问题原因
你当前遇到的进度条异常跳动,核心原因是AudioService.positionStream是内部基于定时器模拟输出的时间流,弱网环境下播放器进入缓冲状态暂停播放时,该定时器不会同步停止,依然会持续推送递增的时间值,导致进度条和实际播放进度脱节。
修改步骤
1. 扩展MediaState结构,增加播放状态属性
首先你需要在现有的MediaState类中新增PlaybackState字段,用于同步接收播放状态信息:
class MediaState { final MediaItem? mediaItem; final Duration position; final PlaybackState playbackState; // 新增播放状态字段 MediaState(this.mediaItem, this.position, this.playbackState); }
2. 合并播放状态流到监听流中
修改你现有的_mediaStateStream,将AudioService.playbackStateStream合并到组合流中,获取实时的播放状态:
Stream<MediaState> get _mediaStateStream => Rx.combineLatest3<MediaItem?, Duration, PlaybackState, MediaState>( AudioService.currentMediaItemStream, AudioService.positionStream, AudioService.playbackStateStream, // 新增播放状态流监听 (mediaItem, position, playbackState) => MediaState(mediaItem, position, playbackState));
3. 增加缓冲判断逻辑,缓存有效播放位置
在进度条组件所在的State类中新增变量存储上次有效播放位置,修改StreamBuilder的渲染逻辑,缓冲/加载状态下保持进度条不动:
// 新增:存储上次有效播放位置 Duration _lastValidPosition = Duration.zero; StreamBuilder _timeLineSlider(double playbackSlider) { return StreamBuilder<MediaState>( stream: _mediaStateStream, builder: (context, snapshot) { final mediaState = snapshot.data; if (mediaState == null) return const SizedBox.shrink(); _playEnded( mediaState.position.inSeconds ?? 0, mediaState.mediaItem?.duration?.inSeconds ?? 0 ); Duration currentPosition; final processingState = mediaState.playbackState.processingState; // 非缓冲、非加载状态下更新有效位置 if (processingState != AudioProcessingState.buffering && processingState != AudioProcessingState.loading && !mediaState.playbackState.isSeeking) { currentPosition = mediaState.position; _lastValidPosition = currentPosition; } else { // 缓冲/加载状态下复用上次有效位置 currentPosition = _lastValidPosition; // 用户主动seek操作时,即使缓冲也更新位置 if (mediaState.playbackState.isSeeking) { currentPosition = mediaState.position; _lastValidPosition = currentPosition; } } return SeekBar( duration: mediaState.mediaItem?.duration ?? Duration.zero, position: currentPosition, onChangeEnd: AudioService.seekTo ); } ); }
可选优化
如果你底层音频播放器使用的是just_audio,也可以直接监听播放器原生的positionStream,该流会在缓冲时自动暂停输出递增时间,从数据源层面避免进度条异常问题。
内容的提问来源于stack exchange,提问作者Stepan Bezhuk
相关产品推荐
相关产品推荐

