You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 13:39:03