Reputation: 622
I want to download videos from YouTube. I want to get
http://www.youtube.com/watch?v=Fwa_GvIBH38&feature=feedrec_grec_index
To
http://o-o.preferred.btcl-dac1.v6.lscache4.c.youtube.com/videoplayback?sparams=id%2Cexpire%2Cip%2Cipbits%2Citag%2Csource%2Calgorithm%2Cburst%2Cfactor%2Ccp&fexp=914016%2C904443&algorithm=throttle-factor&itag=34&ip=58.0.0.0&burst=40&sver=3&signature=82D07EBDBED8BC79D08AEE3F90B1473E44D4065E.88AB21BBB9E2D252B65FE6C419CD7867CDE8815C&source=youtube&expire=1322694000&key=yt1&ipbits=8&factor=1.25&cp=U0hRR1ZUUl9FSkNOMV9OTlZBOmRXLUt2VHYwWVY2&id=1706bf1af2011f7f&ptchn=collegehumor&ptk=collegehumor
I got above link from IDM.
I got two methods from a web site to get above link.
//this methods get's the download link for youtube videos in mp4 format.
public string url(string url)
{
string html = getYoutubeHtml(url);
HtmlAgilityPack.HtmlDocument hDoc = new HtmlDocument();
hDoc.LoadHtml(html);
HtmlNode node = hDoc.GetElementbyId("movie_player");
string flashvars = node.Attributes[5].Value;
string _url = Uri.UnescapeDataString(flashvars);
string[] w = _url.Split('&');
string link = "";
bool foundUrlMap = false;
for (int i = 0; i < w.Length; i++)
{
if (w[i].Contains("fmt_url_map="))
{
foundUrlMap = true;
link += w[i].Split('|')[1];
}
if (foundUrlMap)
{
//add the parameters to the url
link += "&" + w[i];
if (w[i].Contains("id="))
{
link = link.Split(',')[0];
//change the array index for different formats
break;
}
}
}
link = link.Split('|')[1] + "&title=out";
System.Windows.MessageBox.Show(link);
return link;
}
//this method downloads the html code from the youtube page.
private string getYoutubeHtml(string url)
{
string html = "";
WebRequest request = WebRequest.Create(url);
WebResponse response = request.GetResponse();
TextReader reader = new StreamReader(response.GetResponseStream());
string line = "";
while ((line = reader.ReadLine()) != null)
{
html += line;
}
return html;
}
It's not work.ing
It does not find fmt_url_map=
inside of w
So now what can I do?
Upvotes: 0
Views: 8680
Reputation: 2922
The string fmt_url_map doesnt/no longer exists on youtube and the problem with this is, that youtube is a continually evolving beast. That said this will currently work.
The string you currently need to be searching for is "url_encoded_fmt_stream_map" however it is easier again to split by "url=".
I spent a couple of hours testing this today, the strangest point being getting the flashvars string to decode correctly.
string _url = string.Empty;
//Crazy string!
_url = Uri.UnescapeDataString(flashvars);
_url = HttpUtility.HtmlDecode(_url);
_url = HttpUtility.UrlDecode(_url);
_url = Uri.UnescapeDataString(_url);
Which required Uri.UnescapeDataString() twice!
public string url(string url, string videoFormat)
{
HtmlAgilityPack.HtmlDocument hDoc = new HtmlDocument();
hDoc.Load(new WebClient().OpenRead(url));
HtmlNode node = hDoc.GetElementbyId("movie_player");
string flashvars = node.Attributes[5].Value;
string _url = string.Empty;
//Crazy string!
_url = Uri.UnescapeDataString(flashvars);
_url = HttpUtility.HtmlDecode(_url);
_url = HttpUtility.UrlDecode(_url);
_url = Uri.UnescapeDataString(_url);
string[] w = _url.Split(new[] {"url="}, StringSplitOptions.None);
string link = "";
if(!string.IsNullOrEmpty(videoFormat))
{
foreach (string t in w)
{
if(t.Contains("type=") && t.Contains(videoFormat))
{
link = t;
break;
}
}
}
else
{
link = w[1];
}
link += "&title=out";
System.Windows.MessageBox.Show(link);
Process.Start(link);
return link;
}
So for some bonus points the method now accepts a string which you pass the video format you require, "mp4", "x-flv", or "webm".
And it no longer requires your getYoutubeHtml() method, it loads a stream directly from WebClient
HtmlAgilityPack.HtmlDocument hDoc = new HtmlDocument();
hDoc.Load(new WebClient().OpenRead(url));
Upvotes: 2