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
http: ^0.12.0+2 youtube_player_flutter: ^7.0.0+7 cached_network_image: ^2.2.0+1
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
- Go to https://console.developers.google.com/
- Create a new project,
- Click Create Project
- Once done, click Dashboard, Enabled APIs, find YouTube API V3
- Click Enable
- Create Credentials, Choose Youtube API V3
- Select Platform
- Select ‘Public Data’
- Click “What credentials do I need?”
- Click Done
- Copy API Key.
Lets copy this api key into our Flutter project.
String API_KEY = 'AIzaSyBGj_Duj__ivCxJ2ya3ilkVfEzX1ZSRlpE';
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
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; }
ChannelInfo Model class for the above API.
Now let’s use this API in the home screen.
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; }); }
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.
_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), ], ), ), ), ); }
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.
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; }
The VideosList model for the API above
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, }; }
So let’s call this API
_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(() {}); }
and in the build method, we will display it in a ListView
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)), ], ), ), ); }, ),
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.
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; }, ), ), ); } }
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.
hello sir, how to get the duration of the video?