Flutter video caching for 10 seconds on next 4 videos
Asked Answered
K

1

12

Does anyone know how to do Flutter Video Caching in List for 4 to 6 seconds? (For next 5 videos) like Instagram reels.

Is there any way to do it?

I had taken PageView.builder to show a video with a full page.

I have tried one cached_video_player but it's loading full video.

Here is what I have done.

VideoWidget:

typedef OnVideoCompleted = void Function();

class VideoWidget extends StatefulWidget {
  //final bool? play;
  final bool? isDuetVideo;
  final String? url;
  final OnVideoCompleted? onVideoCompleted;
  final HomeWidgetBloc? homeWidgetBloc;

  const VideoWidget(
      {Key? key,
      this.onVideoCompleted,
      required this.url,
      required this.homeWidgetBloc,
      required this.isDuetVideo})
      : super(key: key);

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

class _VideoWidgetState extends State<VideoWidget> {
  late VideoPlayerController videoPlayerController;
  late Future<void> _initializeVideoPlayerFuture;
  final _controllerStateStream = BehaviorSubject<int>.seeded(0);
  VoidCallback? _listener;
  StreamSubscription? _playPauseSubscription;

  @override
  void initState() {
    super.initState();
    videoPlayerController = new VideoPlayerController.network(widget.url!);
    videoPlayerController.initialize().then((_) {
      //       Ensure the first frame is shown after the video is initialized, even before the play button has been pressed.
      _controllerStateStream.add(1);
      _observeForPlayPause();
      _observerForSeekDuration();
      _listener = () {
        final value =
            widget.homeWidgetBloc?.videoEndedStream.valueWrapper?.value;
        print('duration -----value--- ${value}');
        if (videoPlayerController.value.duration.inSeconds > 0 &&
            videoPlayerController.value.position.inMilliseconds ==
                videoPlayerController.value.duration.inMilliseconds &&
            (videoPlayerController.value.position.inMilliseconds ==
                videoPlayerController.value.duration.inMilliseconds)) {
          // FOR AUTO PLAY NEXT VIDEO...
          widget.onVideoCompleted?.call();
          print(
              'duration -----addListener--- ${videoPlayerController.value.duration}');
        }
      };
      videoPlayerController.addListener(_listener!);
    });
  } // This closing tag was missing

  @override
  void dispose() {
    super.dispose();
    _controllerStateStream.close();
    _playPauseSubscription?.cancel();
    try {
      if (_listener != null) {
        videoPlayerController.removeListener(_listener!);
      }
      videoPlayerController.dispose();
    } catch (e) {
      print(e.toString());
    }
  }

  @override
  Widget build(BuildContext context) {
    return StreamBuilder<int>(
      stream: _controllerStateStream,
      builder: (context, snapshot) {
        final isReady = (snapshot.data ?? 0) == 1;

        if (!isReady) {
          return _progressWidget();
        }

        return new Stack(children: <Widget>[
          Container(
            child: Center(
              child: (widget.isDuetVideo! ||
                      videoPlayerController.value.size.width >
                          videoPlayerController.value.size.height)
                  ? AspectRatio(
                      child: VideoPlayer(
                        videoPlayerController,
                      ),
                      aspectRatio: videoPlayerController.value.aspectRatio,
                    )
                  : VideoPlayer(
                      videoPlayerController,
                    ),
              widthFactor: double.maxFinite,
              heightFactor: double.maxFinite,
            ),
          ),
          Visibility(
            visible: !widget.isDuetVideo!,
            child: VideoPlayerCustomControlsWidget(
              controller: videoPlayerController,
            ),
          ),
        ]);
      },
    );
  }

  Center _progressWidget() {
    return Center(
      child: CircularProgressIndicator(
        color: AppStyles.primary500Color,
      ),
    );
  }

  void _observeForPlayPause() {
    _playPauseSubscription =
        widget.homeWidgetBloc?.videoPlayPauseStream.listen((value) {
      if (value == PLAY)
        videoPlayerController.play();
      else
        videoPlayerController.pause();
    });
  }

  void _observerForSeekDuration() {
    _playPauseSubscription =
        widget.homeWidgetBloc?.duetVideoSeekDurationZeroStream.listen((value) {
      if (value == true) videoPlayerController.seekTo(Duration.zero);
      widget.homeWidgetBloc?.duetVideoSeekDurationZeroStream.add(false);
    });
  }
}

Update:

I found many answers (like this) but that all answers are only for caching the current video, not the next/prev videos from the list. I want it, especially for the list.

Kaif answered 13/9, 2021 at 18:39 Comment(4)
Please add some code for a minimal reproducible example.Rupert
@GuillaumeRoux check the question is updatedKaif
Commenting for better rich! +1Budde
Even if you cant find a way to cache first 10 seconds programmatically, you can still add a microservice that runs from same server and visits first 10 seconds of videos that should keep the data in cache until client arrives next video. This is not efficient tho.Minima
A
2

this is what I used in my app, preload_page_view, it preloads a specific count of pre/next pages:

  @override
  Widget build(BuildContext context) {
    return new PreloadPageView.builder(
      itemCount: ...,
      itemBuilder: ...,
      onPageChanged: (int position) {...},
      .....
      preloadPagesCount: 3,
      controller: PreloadPageController(),
    );
  }
Abundance answered 22/9, 2021 at 1:49 Comment(6)
Thanks for the answer, As I am moving to the next video automatically after the current video get completed. Maybe your way will not work to load the next video for some seconds only.Kaif
once the video is pre loaded, can you replay the current video to achieve what you want?Abundance
I am managing the video state to play/pause from anywhere using stream. I don't know what will happen. I need to verify.Kaif
yeh, no problem, hope you sort it out, just an idea that you can seekTo the beginning of current video while switching pagesAbundance
Can you please give me an example, I couldn't able to achieve what I want.Kaif
try to make your page view current index a global variable or put it in state, pass to video widget, fire the event once the current index == video index, _controller.playAbundance

© 2022 - 2025 — McMap. All rights reserved.