anbei eine Überarbeitung eines sehr listigen Werkes von @AliveDevil.
Verwendet wird ein utube-api
zeile#13 ist übrigens eine hardcodet Id, weil ich zu faul bin, bei jedem Testlauf eine gültige Id einzugeben - also die Zeile ist zu löschen, wenn man wirklich eine Id eingeben möchte.
Jo, das Parsen des Video-Infos ist ziemlich krank und krass, das kann ich nicht mehr erklären als im Datei-Kommentar ja bereits steht - sorry .
Ums zu blicken muss man wohl debuggen, und sich
Edit 9-2015: vb-Übersetzung zugefügt
C#-Quellcode
- /*die utube-api returnt "String-Tables" - damit meine ich das format: "name0=value0&name1=value1&name2=value2" usw. Und das verschachtelt sie sogar - die eingeschachtelten Angaben sind aber url-encodet, müssen erstmal decodet werden.
- Also der string-table-eintrag für 'url_encoded_fmt_stream_map' ist eine komma-getrennte Liste weiterer stringTables, jede mit Angaben über einen downloadbaren streams. Aus diesen werden letztlich die StreamInfos generiert.
- Die StreamInfo-Klasse ist bischen ein Hack - ihre Member heissen nämlich wie die Bezeichner der stringTable-Einträge. Auf diese Weise kann man per Reflection mit nur einem Befehl verschiedene Einträge direkt verschiedenen Properties zuweisen, ohne ein Mapping implementieren zu müssen. Die Idee dazu entstammt auch AliveDevils Vorlage.
- */
- namespace UtubeDownloader {
- class Program {
- static void Main(string[] args) {
- Console.WriteLine("Video ID");
- var id = Console.ReadLine();
- id = "eMVNjMF1Suo";
- var client = new WebClient();
- var raw_video_info = client.DownloadString(new Uri("http://youtube.com/get_video_info?&video_id=" + id));
- var rawAllData = ToStringTable(raw_video_info).ToDictionary(entry => entry[0], entry => entry[1]);
- var rawStream_map = HttpUtility.UrlDecode(rawAllData["url_encoded_fmt_stream_map"]);
- var streamInfos = rawStream_map.Split(',').Select(data => StreamInfo.FromStringTable(ToStringTable(data))).ToArray();
- var index = 0;
- Console.WriteLine(string.Join("\n", streamInfos.Select(item => (index++).ToString() + ") " + item.Type + " " + item.Quality)));
- Console.WriteLine("Choose an Index");
- if (int.TryParse(Console.ReadLine(), out index)) {
- var info = streamInfos[index];
- var fileName = ValidFileName(HttpUtility.UrlDecode(rawAllData["title"]));
- var fileType = info.FileType;
- client.DownloadFile(info.DownloadUrl, fileName + "." + fileType);
- }
- }
- private static IEnumerable<string[]> ToStringTable(string s) { return s.Split('&').Select(entry => entry.Split('=')); }
- private static string ValidFileName(string s) { return string.Join("-", s.Split(Path.GetInvalidFileNameChars(), StringSplitOptions.None)); }
- }
- public class StreamInfo {
- private string url;
- private string type;
- public static StreamInfo FromStringTable(IEnumerable<string[]> table) {
- StreamInfo info = new StreamInfo();
- Type infoType = typeof(StreamInfo);
- var properties = infoType.GetProperties().ToDictionary(item => item.Name.ToLower());
- foreach (var entry in table) {
- properties[entry[0].ToLower()].SetValue(info, Convert.ChangeType(entry[1], properties[entry[0].ToLower()].PropertyType));
- }
- return info;
- }
- public string Url {
- get { return url; }
- set { url = HttpUtility.UrlDecode(value); }
- }
- public string Fallback_Host { get; set; }
- public int ITag { get; set; }
- public string Quality { get; set; }
- public string Sig { get; set; }
- public string Type { get { return type; } set { type = HttpUtility.UrlDecode(value); } }
- public string FileType { get { return Type.Split(';')[0].Split('/')[1].Replace("x-", ""); } }
- public string DownloadUrl { get { return string.Format("{0}&fallback_host={1}&signature={2}", Url, Fallback_Host, Sig); } }
- }
- }
get_video_info
- die eine Video-Id verlangt - (zeile #15)zeile#13 ist übrigens eine hardcodet Id, weil ich zu faul bin, bei jedem Testlauf eine gültige Id einzugeben - also die Zeile ist zu löschen, wenn man wirklich eine Id eingeben möchte.
Jo, das Parsen des Video-Infos ist ziemlich krank und krass, das kann ich nicht mehr erklären als im Datei-Kommentar ja bereits steht - sorry .
Ums zu blicken muss man wohl debuggen, und sich
raw_video_info, rawAllData, rawStream_map, streamInfos
im LokalFenster angugge, und auch mal Einträge in einen Editor umkopieren, weil manche der Strings sind lang und inhaltsreich.Edit 9-2015: vb-Übersetzung zugefügt
Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „ErfinderDesRades“ ()