Extracting MP4 Video Link from YouTube for Flutter Apps Streaming

Mohammad Al Kalaleeb
3 min readFeb 17, 2021
Photo by Hello I'm Nik 🎞 on Unsplash

Warning

I do not support or encourage anyone to download or stream copyright videos in violation of YouTube’s terms and conditions. Before downloading or streaming a YouTube video, you are suggested to seek permission from the video owner to download or stream videos legally. This article is for educational purposes only.

First we should have the ID of the video

youtube.com/watch?v=L7T6UO

in this case the id is L7T6UO

we can do that automatically using the code:

static String _getVideoId(String url) {
try {
var id = '';
id = url.substring(url.indexOf('?v=') + '?v='.length);

return 'https://www.youtube.com/get_video_info?video_id=${id}&el=embedded&ps=default&eurl=&gl=US&hl=en';
} catch (e) {
return null;
}
}

Then we can use this to get the info of the video using Dio, or Http Client.

static Future<List<String>> getVideoUrlFromYoutube(String youtubeUrl) async {
// Extract the info url using the past method
var link = _getVideoId(youtubeUrl);

// Checker if the link is valid
if (link == null) {
print('Null Video Id from Link: $youtubeUrl');
Logger().error('Player Error', 'Null Video Id from Link: $youtubeUrl');
}

// Links Holder
var links = <String>[]; // This could turn into a map if one desires it

// Now make the request
var networkClient = Dio();
var response = await networkClient.get(link);

// To make autocomplete easier
var responseText = response.data.toString();

// This sections the chuck of data into multiples so we can parse it
var sections = Uri.decodeFull(responseText).split('&');

// This is the response json we are looking for
var playerResponse = <String, dynamic>{};

// Optimized better
for (int i = 0; i < sections.length; i++) {
String s = sections[i];

// We can have multiple '=' inside the json, we want to divide the chunk by only the first equal
int firstEqual = s.indexOf('=');

// Sanity Check
if (firstEqual < 0) {
continue;
}

// Here we create the key value of the chunk of data
String key = s.substring(0, firstEqual);
String value = s.substring(firstEqual + 1);

// This is the key that holds the mp4 information
if (key == 'player_response') {
playerResponse = jsonDecode(value);
break;
}
}

// Now that we have the json we need, we can start pointing to the links that holds the mp4
// The node we need
Map data = playerResponse['streamingData'];

// Aggregating the data
if (data['formats'] != null) {
var formatLinks = [];
formatLinks = data['formats'];
if (formatLinks != null) {
formatLinks.forEach((element) {
// you can read the map here to get additional video infomation
// like quality width height and bitrate
// For this example however I just want the url
links.add(element['url']);
});
}
}

// And adaptive ones also
if (data['adaptiveFormats'] is List) {
var formatLinks = [];
formatLinks = data['adaptiveFormats'];
formatLinks.forEach((element) {
// you can read the map here to get additional video infomation
// like quality width height and bitrate
// For this example however I just want the url
links.add(element['url']);
});
}

// Finally return the links for the player
return links.isNotEmpty
? links
: [
'<Holder Video>' // This video Url will be the url we will use if there is an error with the method. Because we don't want to break do we? :)
];

}

Now we can use this method in the video player. i found flick player to be really good to shorten the code, so here we go with flick player:

class MyApp extends StatelessWidget {

@override
Widget build(BuildContext context) {
return Scaffold(
body: FutureBuilder(
future: VideoUrlExtractor.getVideoUrlFromYoutube('youtube.com/watch?v=L7T6U'),
builder: (BuildContext context, AsyncSnapshot<List<String>> snapshot) {
if (snapshot.hasData) {
flickManager = FlickManager(
videoPlayerController: VideoPlayerController.network(snapshot.data[0]),
);
return FlickVideoPlayer(flickManager: flickManager);
} else {
return Container();
}
},
),
);
}
}

And that’s it for today.

--

--

Mohammad Al Kalaleeb

Android to the core, AI and Machine Learning Enthusiast.