Flutter Movies App — YouTube Video Support | Part 3

Jackie Moraa
6 min readJun 17, 2023

--

Welcome to part 3 of our Flutter Movies App. In part 2, we successfully implemented the add to list (favourites) feature. In case you missed it, you can catch up with it here.

In this article, we’ll be implementing another nice-to-have feature in our movies app which is the Watch Trailer feature. Creating captivating user experiences is crucial in the success of any application. Providing your users with the ability to watch videos from within the application or to interact with other multimedia content seamlessly goes a long way in ensuring you’ll stand out from other similar apps.

Let’s look at some packages that will allow you to add videos to you app!

Flutter Video Packages Examples

Flutter provides a number of packages that make it easy to incorporate video in your Flutter applications. See a few of them below:

  1. video_player
    This is the official Flutter plugin for Android, iOS and Web for playing videos on a widget surface. This package can be used to display videos from network URLs or local asset files. It supports the common video formats.
  2. chewie
    This package is built on top of the video_player plugin. The video_player plugin provides low-level access to video playback and the chewie plugin wraps this in a friendlier Material or Cupertino UI. This in turn makes it simpler and the UI more customisable for video playback. Chewie supports full-screen mode, auto-playing and custom controls.
  3. youtube_player_flutter
    This is a Flutter package for playing YouTube videos. YouTube videos are embedded into the application by specifying the video ID or YouTube URL. It also supports options like controlling playback and showing / hiding controls.
  4. flutter_vlc_player
    This is a VLC powered alternative to the video_player package supporting iOS and Android. It provides more advanced video playback capabilities because it integrates the VLC media player into the Flutter application which supports a range of video formats. It also provides features like subtitles, and audio selection.

Watch Trailer Feature

As stated in the beginning, the focus of this article is the next step in our Flutter application which is to add the watch trailer feature. The TMDb API provides this endpoint get movie videos which contains a number of video objects that are related to the movies. E.g., features, interviews, trailers (official and unofficial), behind the scenes, bloopers, tours, teasers etc (snippet shared below). We are going to focus only on the official trailer for this particular feature.

"results": [
...
{
"iso_639_1": "en",
"iso_3166_1": "US",
"name": "Filming in Peru",
"key": "rRe_gQYoRTs",
"site": "YouTube",
"size": 1080,
"type": "Behind the Scenes",
"official": true,
"published_at": "2023-05-25T13:00:21.000Z",
"id": "6472aa36a199a60116c7341f"
},
{
"iso_639_1": "en",
"iso_3166_1": "US",
"name": "Meet the New Characters",
"key": "2evSQ-HhSj8",
"site": "YouTube",
"size": 1080,
"type": "Featurette",
"official": true,
"published_at": "2023-05-10T15:01:00.000Z",
"id": "645cccd8156cc7013ff38824"
},
{
"iso_639_1": "en",
"iso_3166_1": "US",
"name": "Official Trailer",
"key": "itnqEauWQZM",
"site": "YouTube",
"size": 1080,
"type": "Trailer",
"official": true,
"published_at": "2023-04-27T13:00:05.000Z",
"id": "644a7695a76ac50449b3c3e3"
}
...
]

In the dart file, we had a method _getMovieTrailer() which fetched all the movie videos. We are going to modify it a little bit so as to only get the official movie trailer and the trailer’s YouTube ID. If you are new to APIs, check out my previous article which breaks down this code snippet.

  Future<void> _getMovieTrailer() async {
// this url hits the TMDb videos endpoint based on the supplied movieID (the current movie whose videos we want to fetch)
final url = Uri.parse(Constants.baseUrl + widget.movieID + Constants.movieVideos);
final response = await http.get(url);
if (response.statusCode == 200) {
final data = json.decode(response.body);
movieTrailer = data.values.toList()[1];
for (var trailer in movieTrailer) {
// since there are so many types of videos, we just want to get the key to the official trailer
if (trailer['name'] == 'Official Trailer') {
setState(() {
// set the trailer ID fetched from the video object
trailerYouTubeID = trailer['key'];
});
break;
}
}
} else {
throw Exception('Failed to load movie videos.');
}
}

Now that we have the YouTube key, we can proceed with the next step which is fetching that trailer from YouTube and displaying it in our UI. Because the video source for the official trailer is YouTube, we can thus make use of the youtube_player_flutter package.

Add this to your pubspec.yaml file. This can be done easily by running this command from the terminal flutter pub add youtube_player_flutter and this line youtube_player_flutter: ^8.1.2 (version subject to change) will be added in the yaml file. After that, import the package in the dart file (with a stateful widget) where the video will be played.

Before we dive into the implementation, let’s get an understanding of a couple of key components that this package offers. We’ll need to understand them before we can put this feature together.

  • YouTubePlayer
    This is the core component of the package. It represents the YouTube player widget. It is responsible for loading and displaying the YouTube videos within the Flutter application. It has various properties to control the playback and video appearance.
  • YoutubePlayerController
    The purpose of the controller is to control the behaviour of the YouTube player. It allows one to interact with the video with actions such as play, pause, seek, changing the volume etc. An instance of the controller is created and passed to the YoutubePlayer widget to control the video playback.
  • YoutubePlayerFlags
    This class provides various flags to that we can use to configure the behavior of the YouTube player. You can set properties like autoPlay, loop and mute to customise the video playback experience.
  • convertUrlToId
    This YoutubePlayer method allows us to extract the YouTube video ID from a given YouTube video url. The video ID can then be used to load and play the video. It simplifies the process of extracting the video ID from different types of YouTube video urls. (N.B. we won’t be needing this in our app since we are able get the video ID directly from the API using the method above)
  • initialVideoId
    This is a property of the YoutubePlayer that is used to specify the initial YouTube video that should be loaded and played when the YoutubePlayer widget is first rendered. By setting this property, you can instruct the YoutubePlayer widget to automatically load and play a specific YouTube video when it is initially displayed on the screen. This allows you to start the playback of a desired video without any user interaction.

So, let’s put all these together to achieve our functionality :)

Create the YoutubePlayerController in the dart file where the package was imported.

late YoutubePlayerController _controller;

We use the late modifier because this controller will be initialised later in the method called when the ‘watch trailer’ button is clicked as shown below. The trailer will be displayed in an alert dialog, hence that is the widget the method will be returning.

void showMovieTrailerDialog(BuildContext context) {
_controller = YoutubePlayerController(
initialVideoId: trailerYouTubeID,
flags: const YoutubePlayerFlags(
autoPlay: false,
mute: false,
),
);

showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
contentPadding: EdgeInsets.zero,
insetPadding: const EdgeInsets.all(10),
backgroundColor: Colors.transparent,
content: YoutubePlayer( // content of the alert dialog is our YT video
controller: _controller,
showVideoProgressIndicator: true,
onReady: () => debugPrint('Ready'), // for debugging purposes only
bottomActions: [
CurrentPosition(),
ProgressBar(
isExpanded: true,
colors: const ProgressBarColors(
playedColor: Colors.orange,
handleColor: Colors.orangeAccent,
),
),
const PlaybackSpeedButton(),
FullScreenButton(),
],
),
actions: <Widget>[
TextButton(
child: const Text(
'Close',
style: TextStyle(fontSize: 13, color: Colors.white),
),
onPressed: () {
Navigator.of(context).pop();
},
),
],
);
},
);
}

Call the method when the button is pressed.

onPressed: () async {
if (trailerYouTubeID == '') {
const snackBar = SnackBar(
content: Text('Movie trailer not available'),
backgroundColor: CupertinoColors.systemOrange,
);
ScaffoldMessenger.of(context).showSnackBar(snackBar);
} else {
showMovieTrailerDialog(context);
}
}

And voila!

Due to the conversion to GIF, we don’t have sound

PS. Don’t forget to dispose the controller afterwards to properly manage memory usage and avoid memory leaks.

@override
void dispose(){
_controller.dispose();
super.dispose();
}

The updated code can be found in this branch on my GitHub.

“Tell me what ya’ll think down below and let me know if you tried this as well. And don’t forget to like, comment, share and subscribe. It really helps my platform. Also, hit that notification bell so that you don’t miss any posts from me.”
— every YouTube influencer! Lol

I hope you’ve enjoyed this article! As always, thanks for reading ❤

--

--

Jackie Moraa
Jackie Moraa

No responses yet