Search code examples
flutterdartflutter-video-player

How to make Flutter video player only start streaming after user tap play?


I am trying Flutter video_player with chewie. I have tried both examples provided in:

Both work fine. Yet, even when the user does not tap on the screen, the video URL is immediately fetched and downloaded.

How can I postpone the video download until the user’s action?


Solution

  • Modifiying the example from the chewie package and putting it inside of a StatefulWidget, we get:

    import 'package:flutter/material.dart';
    import 'package:video_player/video_player.dart';
    import 'package:chewie/chewie.dart';
    
    class ExampleWidget extends StatefulWidget {
      const ExampleWidget({super.key});
    
      @override
      State<ExampleWidget> createState() => _ExampleWidgetState();
    }
    
    final VideoPlayerController videoPlayerController = VideoPlayerController.networkUrl(
        Uri.parse('https://flutter.github.io/assets-for-api-docs/assets/videos/butterfly.mp4'));
    
    class _ExampleWidgetState extends State<ExampleWidget> {
      late final ChewieController chewieController;
      bool _initialized = false;
    
      @override
      void initState() {
        chewieController = ChewieController(
            videoPlayerController: videoPlayerController, autoPlay: false, looping: true, autoInitialize: false);
      }
    
      @override
      void dispose() {
        videoPlayerController.dispose();
        chewieController.dispose();
        super.dispose();
      }
    
      @override
      Widget build(BuildContext context) {
        return Column(
          children: <Widget>[
            Expanded(
              child: Chewie(controller: chewieController),
            ),
            ElevatedButton(
              onPressed: () async {
                if (!_initialized) {
                  await videoPlayerController.initialize();
                }
                _initialized = true;
                await chewieController.play();
              },
              child: const Text("Play"),
            ),
          ],
        );
      }
    }
    
    void main() => runApp(MaterialApp(
        home: Scaffold(
            backgroundColor: Colors.green,
            appBar: AppBar(),
            body: Builder(builder: (BuildContext context) => _build(context)))));
    
    Widget _build(BuildContext context) {
      return const ExampleWidget();
    }
    

    By setting the autoPlay from the ChewieController to false, the video will not automatically play and by using the chewieController.play(), you can then start the video on pressing a button.

    To also prevent the controller from preloading the video, only initialize the videoPlayerController in the callback method once instead of inside of the initState method.

    This will load the video the first time the Play button is pressed (But remember that in this example clicking inside of the video itself would show the error symbol). Instead you could also display some kind of loading Widget instead while the initialized bool is false and only show the Video Player otherwise. Or set the param showControlsto false inside of the ChewieController.