/// <summary> /// Returns all available URIs (audio-only and video) for the given YouTube ID. /// </summary> public static async Task<YouTubeUri[]> GetUrisAsync(string youTubeId, IResourceNetworkLayer networkLayer, IProgress<float> progress, CancellationToken token) { var urls = new List<YouTubeUri>(); string javaScriptCode = null; var response = await HttpGet("https://www.youtube.com/watch?v=" + youTubeId + "&nomobile=1", networkLayer, progress, token); var match = Regex.Match(response, "url_encoded_fmt_stream_map\": ?\"(.*?)\""); var data = Uri.UnescapeDataString(match.Groups[1].Value); match = Regex.Match(response, "adaptive_fmts\": ?\"(.*?)\""); var data2 = Uri.UnescapeDataString(match.Groups[1].Value); var arr = Regex.Split(data + "," + data2, ",(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)"); // split by comma but outside quotes foreach (var d in arr) { var url = ""; //var connection = ""; //var stream = ""; var signature = ""; var tuple = new YouTubeUri(); foreach (var p in d.Replace("\\u0026", "\t").Split('\t')) { var index = p.IndexOf('='); if (index != -1 && index < p.Length) { try { var key = p.Substring(0, index); var value = Uri.UnescapeDataString(p.Substring(index + 1)); if (key == "url") url = value; //else if (key == "conn") // connection = value; //else if (key == "stream") // stream = value; else if (key == "itag") tuple.Itag = int.Parse(value); else if (key == "type" && (value.Contains("video/mp4") || value.Contains("audio/mp4"))) tuple.Type = value; else if (key == "sig") signature = value; else if (key == "s") { if (javaScriptCode == null) { var javaScriptUri = "http://s.ytimg.com/yts/jsbin/html5player-" + Regex.Match(response, "\"\\\\/\\\\/s.ytimg.com\\\\/yts\\\\/jsbin\\\\/html5player-(.+?)\\.js\"") .Groups[1] + ".js"; javaScriptCode = await HttpGet(javaScriptUri, networkLayer, progress, token); } signature = GenerateSignature(value, javaScriptCode); } } catch (Exception exception) { Debug.WriteLine("YouTube parse exception: " + exception.Message); } } } //if (string.IsNullOrEmpty(url) && !string.IsNullOrEmpty(connection) && !string.IsNullOrEmpty(stream)) //{ // url = connection + "?" + stream; //} if (url.Contains("&signature=") || url.Contains("?signature=")) tuple._url = url; else tuple._url = url + "&signature=" + signature; if (tuple.IsValid) urls.Add(tuple); } return urls.ToArray(); }
/// <summary> /// Returns all available URIs (audio-only and video) for the given YouTube ID. /// </summary> public static async Task <YouTubeUri[]> GetUrisAsync(string youTubeId, IResourceNetworkLayer networkLayer, IProgress <float> progress, CancellationToken token) { var urls = new List <YouTubeUri>(); string javaScriptCode = null; var response = await HttpGet("https://www.youtube.com/watch?v=" + youTubeId + "&nomobile=1", networkLayer, progress, token); var match = Regex.Match(response, "url_encoded_fmt_stream_map\": ?\"(.*?)\""); var data = Uri.UnescapeDataString(match.Groups[1].Value); match = Regex.Match(response, "adaptive_fmts\": ?\"(.*?)\""); var data2 = Uri.UnescapeDataString(match.Groups[1].Value); var arr = Regex.Split(data + "," + data2, ",(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)"); // split by comma but outside quotes foreach (var d in arr) { var url = ""; //var connection = ""; //var stream = ""; var signature = ""; var tuple = new YouTubeUri(); foreach (var p in d.Replace("\\u0026", "\t").Split('\t')) { var index = p.IndexOf('='); if (index != -1 && index < p.Length) { try { var key = p.Substring(0, index); var value = Uri.UnescapeDataString(p.Substring(index + 1)); if (key == "url") { url = value; } //else if (key == "conn") // connection = value; //else if (key == "stream") // stream = value; else if (key == "itag") { tuple.Itag = int.Parse(value); } else if (key == "type" && (value.Contains("video/mp4") || value.Contains("audio/mp4"))) { tuple.Type = value; } else if (key == "sig") { signature = value; } else if (key == "s") { if (javaScriptCode == null) { var javaScriptUri = "http://s.ytimg.com/yts/jsbin/html5player-" + Regex.Match(response, "\"\\\\/\\\\/s.ytimg.com\\\\/yts\\\\/jsbin\\\\/html5player-(.+?)\\.js\"") .Groups[1] + ".js"; javaScriptCode = await HttpGet(javaScriptUri, networkLayer, progress, token); } signature = GenerateSignature(value, javaScriptCode); } } catch (Exception exception) { Debug.WriteLine("YouTube parse exception: " + exception.Message); } } } //if (string.IsNullOrEmpty(url) && !string.IsNullOrEmpty(connection) && !string.IsNullOrEmpty(stream)) //{ // url = connection + "?" + stream; //} if (url.Contains("&signature=") || url.Contains("?signature=")) { tuple._url = url; } else { tuple._url = url + "&signature=" + signature; } if (tuple.IsValid) { urls.Add(tuple); } } return(urls.ToArray()); }