private static async void OnHtmlDownloaded(string response, YouTubeQuality minQuality, YouTubeQuality maxQuality, DecryptSignatureMode decryptSignatureMode, Action<YouTubeUri, Exception> completed) { var urls = new List<YouTubeUri>(); if (sigCodes != null && sigCodes.Count > 0) sigCodes.Clear(); javaScriptCode = string.Empty; try { //var match = Regex.Match(response, "url_encoded_fmt_stream_map\": \"(.*?)\""); var match = Regex.Match(response, "url_encoded_fmt_stream_map\"\\s*:\\s*\"(.*?)\""); 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 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 == "itag") tuple.Itag = int.Parse(value); //else if (key == "type" && (value.Contains("video/mp4") || value.Contains("audio/mp4"))) //只获取Mp4 else if (key == "type") //获取全部 tuple.Type = value; else if (key == "s") { if (decryptSignatureMode == DecryptSignatureMode.DecryptLocalSignature) signature = await DecryptLocalSignature(value, response); else signature = await DecryptWebSignature(value); } else if (key == "sig") signature = value; } catch (Exception exception) { Debug.WriteLine("YouTube parse exception: " + exception.Message); } } } if (url.Contains("&signature=") || url.Contains("?signature=")) tuple.url = url; else tuple.url = url + "&signature=" + signature; if (tuple.IsValid) urls.Add(tuple); } var minTag = GetQualityIdentifier(minQuality); var maxTag = GetQualityIdentifier(maxQuality); //foreach (var u in urls.Where(u => u.Itag < minTag || u.Itag > maxTag).ToArray()) //得到相对命中的,如果没用命中绝对项,会找到目标项[上一级或下一级(相邻)]的项 foreach (var u in urls.Where(u => u.Itag <= minTag || u.Itag >= maxTag).ToArray()) //得到绝对命中的 urls.Remove(u); } catch (Exception ex) { if (completed != null) completed(null, ex); return; } var entry = urls.OrderByDescending(u => u.Itag).FirstOrDefault(); if (entry != null) { if (completed != null) completed(entry, null); } else if (completed != null) //completed(null, new Exception("no_video_urls_found")); completed(entry, null); }
public static async Task<YouTubeUri> GetVideoUriAsync(string youTubeId, YouTubeQuality maxQuality = YouTubeQuality.Quality360P_MP4, DecryptSignatureMode decryptSignatureMode = DecryptSignatureMode.DecryptLocalSignature) { //HttpClientHandler handler = new HttpClientHandler(); //handler.UseDefaultCredentials = true; //handler.AllowAutoRedirect = true; //handler.CookieContainer = new CookieContainer(); //using (var client = new HttpClient(handler)) using (var client = new HttpClient()) { //client.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)"); //client.DefaultRequestHeaders.Add("Accept", "text/html"); client.DefaultRequestHeaders.Add("User-Agent", BotUserAgent); var response = await client.GetAsync("https://www.youtube.com/watch?v=" + youTubeId + "&nomobile=1"); var task = new TaskCompletionSource<YouTubeUri>(); OnHtmlDownloaded(await response.Content.ReadAsStringAsync(), YouTubeQuality.QualityMP3_FLV_22KHZ, maxQuality, decryptSignatureMode, (u, e) => { if (u != null) task.SetResult(u); else if (e == null) task.SetResult(u); //task.SetCanceled(); else task.SetException(e); }); return await task.Task; } }
public static async Task<List<YouTubeUri>> GetVideoAllUrisAsync(string youTubeId, YouTubeFormat youTubeFormat = YouTubeFormat.All, DecryptSignatureMode decryptSignatureMode = DecryptSignatureMode.DecryptLocalSignature) { using (var client = new HttpClient()) { client.DefaultRequestHeaders.Add("User-Agent", BotUserAgent); var response = await client.GetAsync("https://www.youtube.com/watch?v=" + youTubeId + "&nomobile=1"); var task = new TaskCompletionSource<List<YouTubeUri>>(); OnHtmlParse(await response.Content.ReadAsStringAsync(), decryptSignatureMode, (u, e) => { if (u != null) { List<YouTubeUri> result = null; if (youTubeFormat == YouTubeFormat.All) { result = u; } else if (youTubeFormat == YouTubeFormat.Flv || youTubeFormat == YouTubeFormat.Mp3) { //List<int> result = u.Select(uAll => uAll.Itag).Concat(FormatCodeFlvOrMp3).ToList(); result = (from uAll in u from flvOrMp3 in FormatCodeFlvOrMp3 where uAll.Itag == flvOrMp3 select uAll).ToList(); } else if (youTubeFormat == YouTubeFormat.Mp4) { result = (from uAll in u from mp4 in FormatCodeMp4 where uAll.Itag == mp4 select uAll).ToList(); } else if (youTubeFormat == YouTubeFormat.MP4OrFlv_mp3) { result = (from uAll in u from mP4OrFlv_mp3 in FormatCodeMP4OrFlv_mp3 where uAll.Itag == mP4OrFlv_mp3 select uAll).ToList(); } else { result = (from uAll in u from quality in FormatCodeQuality where uAll.Itag == quality select uAll).ToList(); } task.SetResult(result); } else if (e == null) { //task.SetCanceled(); task.SetResult(u); } else task.SetException(e); }); return await task.Task; } }