This document provides an overview of a custom video player widget built using Chewie and video_player packages. This custom video player is designed to be used within a FlutterFlow project.
Introduction
Having worked through a number of examples shared within the community, I found that, over time, these examples have become unusable, either because they were incomplete, or that packages and solutions become superseded.
My requirement was quite simple. I wanted the ability to display a full-screen video with audio in portrait mode, which autoplays when the page is loaded, taking the file from Firebase storage. I also wanted the ability to pause and restart the image when tapping on the screen. After a bit of playing around with the scarce documentation online, I finally got the solution working, which I am happy to share with the wider FF community.
Overview
This custom video player widget uses chewie, a wrapper around video_player, to provide a more user-friendly video player interface. The widget allows playing videos from network URLs, with features such as play/pause on tap, volume control, and aspect ratio adjustments.
Dependencies
Make sure you have the following dependencies in Flutterflow:
chewie: 1.7.5
video_player: (Use the one in Flutterflow)
Code
// Automatic FlutterFlow imports
import '/flutter_flow/flutter_flow_theme.dart';
import '/flutter_flow/flutter_flow_util.dart';
import '/custom_code/widgets/index.dart'; // Imports other custom widgets
import '/flutter_flow/custom_functions.dart'; // Imports custom functions
import 'package:flutter/material.dart';
// Begin custom widget code
// DO NOT REMOVE OR MODIFY THE CODE ABOVE!import 'package:video_player/video_player.dart';
import 'package:chewie/chewie.dart';// Define a custom widget named CustomVidPlayer
class CustomVidPlayer extends StatefulWidget {
CustomVidPlayer({
this.width,
this.height,
required this.videoPath,
}); final double? width;
final double? height;
final String videoPath; @override
_CustomVidPlayerState createState() => _CustomVidPlayerState();
}class _CustomVidPlayerState extends State<CustomVidPlayer> {
late VideoPlayerController _videoPlayerController;
late ChewieController _chewieController;
late Future<void> _initializeVideoPlayerFuture; double videoContainerRatio = 0.5; @override
void initState() {
super.initState();
_videoPlayerController =
VideoPlayerController.networkUrl(Uri.parse(widget.videoPath));
_initializeVideoPlayerFuture = _videoPlayerController.initialize();
_videoPlayerController.setVolume(1.0);
} @override
void dispose() {
_videoPlayerController.dispose();
_chewieController.dispose();
super.dispose();
} @override
Widget build(BuildContext context) {
return FutureBuilder(
future: _initializeVideoPlayerFuture,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
_chewieController = ChewieController(
videoPlayerController: _videoPlayerController,
aspectRatio: _videoPlayerController.value.aspectRatio,
autoInitialize: true,
looping: false,
showControls: false,
autoPlay: true,
); return Container(
child: Transform.scale(
scale: getScale(),
child: AspectRatio(
aspectRatio: _videoPlayerController.value.aspectRatio,
child: Stack(
children: [
// Display the video using Chewie
Chewie(
controller: _chewieController,
),
GestureDetector(
onTap: toggleVideoPlayback, // play / pause video on tap
behavior: HitTestBehavior.opaque,
),
],
),
),
),
);
} else {
return Center(
child: CircularProgressIndicator(),
);
}
},
);
} double getScale() {
double videoRatio = _videoPlayerController.value.aspectRatio; if (videoRatio < videoContainerRatio) {
///for tall videos, we just return the inverse of the controller aspect ratio
return videoContainerRatio / videoRatio;
} else {
///for wide videos, divide the video AR by the fixed container AR
///so that the video does not over scale
return videoRatio / videoContainerRatio;
}
} void toggleVideoPlayback() {
if (_videoPlayerController.value.isPlaying) {
_chewieController.pause();
print("Paused");
} else {
_chewieController.play();
print("Playing");
}
}
}Parameters
What’s Going On?
Imports and Initialization:
The required packages and dependencies are imported.
VideoPlayerControllerfromvideo_playerpackage andChewieControllerfromchewiepackage are used.
CustomVidPlayer Widget:
This widget takes
width,height, andvideoPathas parameters.widthandheightdefine the size of the video player.videoPathis the URL of the video to be played.
State Management:
_CustomVidPlayerStatemanages the state of the video player.The
initStatemethod initializes the video player with the provided video URL and sets the volume.
Video Player Initialization:
_initializeVideoPlayerFutureis used to handle the asynchronous initialization of the video player.
Dispose Method:
The
disposemethod disposes of the video player controller and chewie controller to free up resources.
Build Method:
The
buildmethod uses aFutureBuilderto ensure the video is loaded before displaying it.A
ChewieControlleris created to manage the video player settings such as aspect ratio, auto play, and looping.The
Containerwidget usesTransform.scaleto maintain the aspect ratio and scale of the video.
Helper Methods:
getScalemethod adjusts the scale of the video based on its aspect ratio.toggleVideoPlaybackmethod toggles the video playback between play and pause on tap.
Notes
The
Chewiepackage provides a simplified wrap around the video_player interface with custom controls.Ensure to use compatible versions of
chewieandvideo_playerto avoid conflicts with other dependencies, such as provider.
This documentation should help developers understand and use the custom video player widget in their FlutterFlow projects.
Happy Coding.
Article originally published here: Flutterflow Custom Video Player. Video Player Widget (Chewie) | by Rocco Labellarte | May, 2024 | Medium