How to use YouTube APIs and Play YouTube videos in Flutter.

By | August 27, 2020

In this article we are gonna talk about how to use YouTube API’s and play YouTube videos in Flutter.

Watch Video Tutorial


Add Dependencies

Open pubspec.yaml file in your Flutter project and add below dependencies

[java]
http: ^0.12.0+2
youtube_player_flutter: ^7.0.0+7
cached_network_image: ^2.2.0+1
[/java]

Now, Let’s create two screens

  • Home Screen
  • Video Player Screen

In the HomeScreen we will show the list of videos.


API Key

We need the API key to access the YouTube APIs.

For that we need to

  1. Go to https://console.developers.google.com/
  2. Create a new project, 
  3. Click Create Project
  4. Once done, click Dashboard, Enabled APIs, find YouTube API V3
  5. Click Enable
  6. Create Credentials, Choose Youtube API V3
  7. Select Platform
  8. Select ‘Public Data’
  9. Click “What credentials do I need?”
  10. Click Done
  11. Copy API Key.

Lets copy this api key into our Flutter project.

[java]
String API_KEY = ‘AIzaSyBGj_Duj__ivCxJ2ya3ilkVfEzX1ZSRlpE’;
[/java]


Get the Channel Info

To Get the channel info, we can use the below youtube API

Let’s create a Services class to call these APIs.

Create a class named “Services.dart and call the above API.


Get the channel ID of one of the YouTube Channels.

Below is my Channel’s ID.
https://www.youtube.com/channel/UC5lbdURzjB0irr-FTbjWN1A

[java]
static const CHANNEL_ID = ‘UC5lbdURzjB0irr-FTbjWN1A’;
static const _baseUrl = ‘www.googleapis.com’;
static Future<ChannelInfo> getChannelInfo() async {
Map<String, String> parameters = {
‘part’: ‘snippet,contentDetails,statistics’,
‘id’: CHANNEL_ID,
‘key’: Constants.API_KEY,
};
Map<String, String> headers = {
HttpHeaders.contentTypeHeader: ‘application/json’,
};
Uri uri = Uri.https(
_baseUrl,
‘/youtube/v3/channels’,
parameters,
);
Response response = await http.get(uri, headers: headers);
// print(response.body);
ChannelInfo channelInfo = channelInfoFromJson(response.body);
return channelInfo;
}
[/java]

ChannelInfo Model class for the above API.

Now let’s use this API in the home screen.

[java]
ChannelInfo _channelInfo;
_getChannelInfo() async {
_channelInfo = await Services.getChannelInfo();
_item = _channelInfo.items[0];
_playListId = _item.contentDetails.relatedPlaylists.uploads;
print(‘_playListId $_playListId’);
await _loadVideos();
setState(() {
_loading = false;
});
}
[/java]


Let’s build the Channel Info View.

_item.snippet.title. - gets the channel title
_item.snippet.thumbnails.medium.url - gets the channel thumbnail image. in medium resolution.

[java]
_buildInfoView() {
return _loading
? CircularProgressIndicator()
: Container(
padding: EdgeInsets.all(20.0),
child: Card(
child: Padding(
padding: const EdgeInsets.all(10.0),
child: Row(
children: [
CircleAvatar(
backgroundImage: CachedNetworkImageProvider(
_item.snippet.thumbnails.medium.url,
),
),
SizedBox(width: 20),
Expanded(
child: Text(
_item.snippet.title,
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.w400,
),
),
),
Text(_item.statistics.videoCount),
SizedBox(width: 20),
],
),
),
),
);
}
[/java]


Get the Videos List

To get the videos list, we need to use the YouTube API below…

https://developers.google.com/youtube/v3/docs/playlistItems/list

Let’s write the service for getting the video list.

[java]
static Future<VideosList> getVideosList(
{String playListId, String pageToken}) async {
Map<String, String> parameters = {
‘part’: ‘snippet’,
‘playlistId’: playListId,
‘maxResults’: ‘8’,
‘pageToken’: pageToken,
‘key’: Constants.API_KEY,
};
Map<String, String> headers = {
HttpHeaders.contentTypeHeader: ‘application/json’,
};
Uri uri = Uri.https(
_baseUrl,
‘/youtube/v3/playlistItems’,
parameters,
);
Response response = await http.get(uri, headers: headers);
// print(response.body);
VideosList videosList = videosListFromJson(response.body);
return videosList;
}
[/java]


The VideosList model for the API above

[java]
import ‘dart:convert’;
VideosList videosListFromJson(String str) =>
VideosList.fromJson(json.decode(str));
String videosListToJson(VideosList data) => json.encode(data.toJson());
class VideosList {
VideosList({
this.kind,
this.etag,
this.nextPageToken,
this.videos,
this.pageInfo,
});
String kind;
String etag;
String nextPageToken;
List<VideoItem> videos;
PageInfo pageInfo;
factory VideosList.fromJson(Map<String, dynamic> json) => VideosList(
kind: json["kind"],
etag: json["etag"],
nextPageToken: json["nextPageToken"],
videos: List<VideoItem>.from(
json["items"].map((x) => VideoItem.fromJson(x))),
pageInfo: PageInfo.fromJson(json["pageInfo"]),
);
Map<String, dynamic> toJson() => {
"kind": kind,
"etag": etag,
"nextPageToken": nextPageToken,
"items": List<dynamic>.from(videos.map((x) => x.toJson())),
"pageInfo": pageInfo.toJson(),
};
}
class VideoItem {
VideoItem({
this.kind,
this.etag,
this.id,
this.video,
});
String kind;
String etag;
String id;
Video video;
factory VideoItem.fromJson(Map<String, dynamic> json) => VideoItem(
kind: json["kind"],
etag: json["etag"],
id: json["id"],
video: Video.fromJson(json["snippet"]),
);
Map<String, dynamic> toJson() => {
"kind": kind,
"etag": etag,
"id": id,
"snippet": video.toJson(),
};
}
class Video {
Video({
this.publishedAt,
this.channelId,
this.title,
this.description,
this.thumbnails,
this.channelTitle,
this.playlistId,
this.position,
this.resourceId,
});
DateTime publishedAt;
String channelId;
String title;
String description;
Thumbnails thumbnails;
String channelTitle;
String playlistId;
int position;
ResourceId resourceId;
factory Video.fromJson(Map<String, dynamic> json) => Video(
publishedAt: DateTime.parse(json["publishedAt"]),
channelId: json["channelId"],
title: json["title"],
description: json["description"],
thumbnails: Thumbnails.fromJson(json["thumbnails"]),
channelTitle: json["channelTitle"],
playlistId: json["playlistId"],
position: json["position"],
resourceId: ResourceId.fromJson(json["resourceId"]),
);
Map<String, dynamic> toJson() => {
"publishedAt": publishedAt.toIso8601String(),
"channelId": channelId,
"title": title,
"description": description,
"thumbnails": thumbnails.toJson(),
"channelTitle": channelTitle,
"playlistId": playlistId,
"position": position,
"resourceId": resourceId.toJson(),
};
}
class ResourceId {
ResourceId({
this.kind,
this.videoId,
});
String kind;
String videoId;
factory ResourceId.fromJson(Map<String, dynamic> json) => ResourceId(
kind: json["kind"],
videoId: json["videoId"],
);
Map<String, dynamic> toJson() => {
"kind": kind,
"videoId": videoId,
};
}
class Thumbnails {
Thumbnails({
this.thumbnailsDefault,
this.medium,
this.high,
this.standard,
this.maxres,
});
Default thumbnailsDefault;
Default medium;
Default high;
Default standard;
Default maxres;
factory Thumbnails.fromJson(Map<String, dynamic> json) => Thumbnails(
thumbnailsDefault: Default.fromJson(json["default"]),
medium: Default.fromJson(json["medium"]),
high: Default.fromJson(json["high"]),
standard: null == json["standard"]
? null
: Default.fromJson(json["standard"]),
maxres:
null == json["maxres"] ? null : Default.fromJson(json["maxres"]),
);
Map<String, dynamic> toJson() => {
"default": thumbnailsDefault.toJson(),
"medium": medium.toJson(),
"high": high.toJson(),
"standard": standard.toJson(),
"maxres": maxres.toJson(),
};
}
class Default {
Default({
this.url,
this.width,
this.height,
});
String url;
int width;
int height;
factory Default.fromJson(Map<String, dynamic> json) => Default(
url: json["url"],
width: json["width"],
height: json["height"],
);
Map<String, dynamic> toJson() => {
"url": url,
"width": width,
"height": height,
};
}
class PageInfo {
PageInfo({
this.totalResults,
this.resultsPerPage,
});
int totalResults;
int resultsPerPage;
factory PageInfo.fromJson(Map<String, dynamic> json) => PageInfo(
totalResults: json["totalResults"],
resultsPerPage: json["resultsPerPage"],
);
Map<String, dynamic> toJson() => {
"totalResults": totalResults,
"resultsPerPage": resultsPerPage,
};
}
[/java]


So let’s call this API

[java]
_loadVideos() async {
VideosList tempVideosList = await Services.getVideosList(
playListId: _playListId,
pageToken: _nextPageToken,
);
_nextPageToken = tempVideosList.nextPageToken;
_videosList.videos.addAll(tempVideosList.videos);
print(‘videos: ${_videosList.videos.length}’);
print(‘_nextPageToken $_nextPageToken’);
setState(() {});
}
[/java]

and in the build method, we will display it in a ListView

[java]
ListView.builder(
controller: _scrollController,
itemCount: _videosList.videos.length,
itemBuilder: (context, index) {
VideoItem videoItem = _videosList.videos[index];
return InkWell(
onTap: () async {
Navigator.push(context,
MaterialPageRoute(builder: (context) {
return VideoPlayerScreen(
videoItem: videoItem,
);
}));
},
child: Container(
padding: EdgeInsets.all(20.0),
child: Row(
children: [
CachedNetworkImage(
imageUrl: videoItem
.video.thumbnails.thumbnailsDefault.url,
),
SizedBox(width: 20),
Flexible(child: Text(videoItem.video.title)),
],
),
),
);
},
),
[/java]


Video Player Screen

So now we have each Video Item, each of them have a videoId which can be used to Load the Video.
The Video Player Screen will accept the VideoItem Model from above and play the video.

[java]
import ‘package:flutter/material.dart’;
import ‘package:flutter_demos/models/viideos_list.dart’;
import ‘package:youtube_player_flutter/youtube_player_flutter.dart’;
class VideoPlayerScreen extends StatefulWidget {
//
VideoPlayerScreen({this.videoItem});
final VideoItem videoItem;
@override
_VideoPlayerScreenState createState() => _VideoPlayerScreenState();
}
class _VideoPlayerScreenState extends State<VideoPlayerScreen> {
//
YoutubePlayerController _controller;
bool _isPlayerReady;
@override
void initState() {
super.initState();
_isPlayerReady = false;
_controller = YoutubePlayerController(
initialVideoId: widget.videoItem.video.resourceId.videoId,
flags: YoutubePlayerFlags(
mute: false,
autoPlay: true,
),
)..addListener(_listener);
}
void _listener() {
if (_isPlayerReady && mounted && !_controller.value.isFullScreen) {
//
}
}
@override
void deactivate() {
_controller.pause();
super.deactivate();
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.videoItem.video.title),
),
body: Container(
child: YoutubePlayer(
controller: _controller,
showVideoProgressIndicator: true,
onReady: () {
print(‘Player is ready.’);
_isPlayerReady = true;
},
),
),
);
}
}
[/java]


Source Code

https://bitbucket.org/vipinvijayan1987/tutorialprojects/src/YoutubePlayer/FlutterTutorialProjects/flutter_demos/

That’s it.

Watch my YouTube video tutorial for more detailed explanation.

Thanks for reading.


One thought on “How to use YouTube APIs and Play YouTube videos in Flutter.

Leave a Reply

Your email address will not be published. Required fields are marked *