Making a video player with controls from scratch in flutter can be not an easy task. Chewie package comes with 3 built-in ui controls for video player. For android, it’s MaterialUI
, for ios it’s CupertinoUI
and for desktop it’s MaterialDesktopUI
. You can also create options which will control video, By default it comes with playback speed and subtitles options. Now let’s start with adding necessary dependencies.
dependencies:
...
chewie: ^1.3.3
video_player: ^2.4.2
...
flutter:
assets:
- file.mp4 # short video file for testing is ./assets directory
Chewie uses video_player package under the hood to play video. So, we need to add video_player dependency.
Project Structure
/
├── assets/
│ └── file.mp4
├── lib/
│ ├── main.dart
│ └── video_page.dart
└── pubspec.yaml
Add VideoPage
widget in home named parameter of the MaterialApp widget. VideoPage will be stateful widget. We need two controllers, one for video_player and another for chewie. We will initialize them in an async function. First we will initialize _videoPlayerController
and then we will call initialize()
method on _videoPlayerController which is Future so we need to prefix it await, then we will initialize _chewieController
and pass the _videoPlayerController to it. Lastly call setState() to update the state.
_initControllers() async {
_videoPlayerController = VideoPlayerController.asset('assets/file.mp4');
await _videoPlayerController.initialize();
_chewieController = ChewieController(
videoPlayerController: _videoPlayerController,
);
setState(() {});
}
In our build method pass FutureBuilder to Scaffold widget. Now pass _initControllers
method to FutureBuilder’s future parameter. Then in builder method we will first check if connectionState is waiting then we will return CircularProgressIndicator widget. If connectionState is done, first we will copy aspect ratio from _videoPlayerController
to _chewieController
then we will return Chewie video player widget.
Widget build(BuildContext context) {
return Scaffold(
body: FutureBuilder(
future: _initControllers(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(child: CircularProgressIndicator());
}
if (snapshot.connectionState == ConnectionState.done) {
_chewieController.copyWith(
aspectRatio: _videoPlayerController.value.aspectRatio,
);
}
return Center(
child: AspectRatio(
aspectRatio: _chewieController.aspectRatio!,
child: Chewie(controller: _chewieController),
),
);
}),
);
}
And at last dispose controllers in dispose method.
@override
void dispose() {
_videoPlayerController.dispose();
_chewieController.dispose();
super.dispose();
}