带有进度条的 Flutter 背景音频

Flutter background audio with progressbar

我想播放流中的音频。我用过Just Audio for this. I want a progress bar like Audio Video Progress bar also play the audio in the background using Audio Service.

我已经使用了所有示例,它们是单独工作的,但我无法将它们串联起来。你能帮忙举例说明我该怎么做吗?

example from audio_service plugin contains how to use audio_service along with just_audio。 (合并 2 个包完成)

下面是audio_service插件示例中提到的SeekBar

// A seek bar.
StreamBuilder<MediaState>(
    stream: _mediaStateStream,
    builder: (context, snapshot) {
        final mediaState = snapshot.data;
        return SeekBar(
            duration:
                mediaState?.mediaItem?.duration ?? Duration.zero,
            position: mediaState?.position ?? Duration.zero,
            onChangeEnd: (newPosition) {
                AudioService.seekTo(newPosition);
            },
        );
    },
),
...

class SeekBar extends StatefulWidget {
  final Duration duration;
  final Duration position;
  final ValueChanged<Duration>? onChanged;
  final ValueChanged<Duration>? onChangeEnd;

  SeekBar({
    required this.duration,
    required this.position,
    this.onChanged,
    this.onChangeEnd,
  });

  @override
  _SeekBarState createState() => _SeekBarState();
}

// more code in the plugin example

现在从上面的代码可以看出,示例使用了自定义设计的SeekBar(它使用了slider)。

您可以使用您想要的插件小部件,而不是自定义滑块。 ProgressBar 你的情况。

StreamBuilder<MediaState>(
    stream: _mediaStateStream,
    builder: (context, snapshot) {
        final mediaState = snapshot.data;
        return ProgressBar(
            total:
                mediaState?.mediaItem?.duration ?? Duration.zero,
            progress: mediaState?.position ?? Duration.zero,
            onSeek: (newPosition) {
                AudioService.seekTo(newPosition);
            },
        );
    },
),

这是对上述 SeekBarProgressBar 的更改。 (结合第三个包完成)

注:为buffered。您可以从 audio_service PlaybackStateStream.

中获取 bufferedPosition

编辑: 下面是我如何使用它来添加 bufferedPosition.

(我把MediaStateclass,对应状态getter改了一下就实现了)

StreamBuilder<MediaState>(
    stream: _mediaStateStream,
    builder: (context, snapshot) {
        final mediaState = snapshot.data;
        return ProgressBar(
            total:
                mediaState?.mediaItem?.duration ?? Duration.zero,
            progress: mediaState?.position ?? Duration.zero,
            buffered: mediaState?.playbackState?
                .bufferedPosition ?? Duration.zero,
            onSeek: (newPosition) {
                AudioService.seekTo(newPosition);
            },
        );
    },
),
...
Stream<MediaState> get _mediaStateStream =>
  Rx.combineLatest3<MediaItem, Duration, PlaybackState, MediaState>(
      AudioService.currentMediaItemStream,
      AudioService.positionStream,
      AudioService.playbackStateStream,
      (mediaItem, position, playbackState) =>
          MediaState(mediaItem, position, playbackState));
...
class MediaState {
  final MediaItem mediaItem;
  final Duration position;
  final PlaybackState playbackState;

  MediaState(this.mediaItem, this.position, this.playbackState);
}