You've already forked N_m3u8DL-CLI
							
							
				mirror of
				https://github.com/nilaoda/N_m3u8DL-CLI
				synced 2025-10-31 18:00:51 +01:00 
			
		
		
		
	Compare commits
	
		
			160 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 71a9878aaa | ||
|   | 769fe4e926 | ||
|   | 1f57ba7c09 | ||
|   | 71282bda30 | ||
|   | 41ee8aebdf | ||
|   | a4537bc093 | ||
|   | b8a60b3917 | ||
|   | 8091dd290f | ||
|   | d48e84e611 | ||
|   | 9f5423a437 | ||
|   | ce7e38770a | ||
|   | 8fdb2e918e | ||
|   | d4b7d240c1 | ||
|   | 484d2941ed | ||
|   | a0f2b66575 | ||
|   | 65cc0681e2 | ||
|   | 7d980ec9a2 | ||
|   | ec5892c05a | ||
|   | 9aed50fbf9 | ||
|   | d657b455cd | ||
|   | cda6575605 | ||
|   | 0d6377d41b | ||
|   | 9c76bdcbce | ||
|   | 83915ff606 | ||
|   | 9cd4746f33 | ||
|   | 33a5b917ac | ||
|   | f69978bd82 | ||
|   | d9fd526886 | ||
|   | 1cc8ecfaaf | ||
|   | 2bc2dde2ad | ||
|   | c3ddcf9e0e | ||
|   | ba5d20dd02 | ||
|   | 16f705fe66 | ||
|   | d141cabc4a | ||
|   | adcf884a93 | ||
|   | 9d903a025f | ||
|   | 0bd23ab641 | ||
|   | a38f27ccd7 | ||
|   | 3acec5efd3 | ||
|   | 90874e4bfe | ||
|   | b94768e3e8 | ||
|   | 311f3b882e | ||
|   | 4b4f537984 | ||
|   | 8032d50b42 | ||
|   | f615764e55 | ||
|   | ccaa200ef8 | ||
|   | 6058d878eb | ||
|   | c712c6dee0 | ||
|   | bb24bb998f | ||
|   | e9d951efa5 | ||
|   | 6f88a805ef | ||
|   | 6aa6d63a8d | ||
|   | 147246caba | ||
|   | 35c1ee4777 | ||
|   | 8b32081b85 | ||
|   | c00de328d1 | ||
|   | d5193c1645 | ||
|   | c06fbf5820 | ||
|   | e700edba56 | ||
|   | aad948da7c | ||
|   | 14f7b20176 | ||
|   | a66a9a4096 | ||
|   | c862f23a9c | ||
|   | 1a722e80de | ||
|   | eff43e8ac3 | ||
|   | 7648f8f8dc | ||
|   | 1edc1a43fe | ||
|   | 01e7735018 | ||
|   | a0c41d6116 | ||
|   | c3c25774de | ||
|   | ba40641a21 | ||
|   | 5d76418780 | ||
|   | fd48b766b5 | ||
|   | 0f25cc0ae8 | ||
|   | 1c6bd688e3 | ||
|   | 480857cc3b | ||
|   | 52af9a44a8 | ||
|   | 84d137b504 | ||
|   | a4f1064c81 | ||
|   | eac08b12f8 | ||
|   | c81c911888 | ||
|   | 361e901e5b | ||
|   | 3567f4c4cc | ||
|   | 2f7b0f7304 | ||
|   | 000d0db4ae | ||
|   | d551ad52c1 | ||
|   | c064c83c21 | ||
|   | f6ed0f9e4d | ||
|   | f65fee94ca | ||
|   | ce64a92b0d | ||
|   | 42790ce540 | ||
|   | 83d8ca1c8c | ||
|   | 4b5a64eb98 | ||
|   | 2b5af09c3b | ||
|   | 6368adc2ab | ||
|   | fcd7840091 | ||
|   | d77cb62dff | ||
|   | 34394c6a2b | ||
|   | 091cba8555 | ||
|   | b02b6b7168 | ||
|   | b7408b0599 | ||
|   | b83cb35170 | ||
|   | ed0a7b71a7 | ||
|   | 50eae19bf3 | ||
|   | cba8f3ea52 | ||
|   | 7fd93e1232 | ||
|   | 74a7e3c3ec | ||
|   | 849d712e11 | ||
|   | 7544f3a02c | ||
|   | 0120736c53 | ||
|   | e4bde4926c | ||
|   | d42cd6a60d | ||
|   | 175f13adc9 | ||
|   | 72f1c043b1 | ||
|   | a2e2070f5d | ||
|   | 6c96deb366 | ||
|   | 2bd900ee5d | ||
|   | 1261810510 | ||
|   | 26823dbd7e | ||
|   | 698699d9fc | ||
|   | ebed7fa1e3 | ||
|   | 73a8348155 | ||
|   | 5ace0b3a4f | ||
|   | 5abe889da0 | ||
|   | f1070fd1b4 | ||
|   | 4af82cc7f9 | ||
|   | 809380b7ab | ||
|   | ab57420507 | ||
|   | 80230f12fe | ||
|   | a6c7c0fd8c | ||
|   | bd6df6b58c | ||
|   | e0a9071d62 | ||
|   | 5c9bcf72d2 | ||
|   | 7cf2c12d0c | ||
|   | 1b35fe2d2c | ||
|   | ed3aae1cb9 | ||
|   | 01c2ecbeb5 | ||
|   | 9993ec8177 | ||
|   | 464300c860 | ||
|   | 45fa58a46f | ||
|   | f93ddc7107 | ||
|   | 05f450fa6d | ||
|   | 580c374d7b | ||
|   | b58dc5d8e0 | ||
|   | f50cf7862a | ||
|   | fdad68d483 | ||
|   | d7aaa5323b | ||
|   | 6c2e13b800 | ||
|   | 086fc57958 | ||
|   | bc349b8977 | ||
|   | cc4efed3c6 | ||
|   | cf958e833b | ||
|   | fb09add0cd | ||
|   | 5a3c5baefd | ||
|   | 839afd8e61 | ||
|   | 338c7a25d0 | ||
|   | f57ce8c2da | ||
|   | a5009e1683 | ||
|   | 66933da9de | ||
|   | 136389e248 | 
							
								
								
									
										34
									
								
								.github/workflows/build_latest.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								.github/workflows/build_latest.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,34 @@ | ||||
| name: Build_Latest | ||||
|   | ||||
| on: [push] | ||||
|   | ||||
| jobs: | ||||
|   build: | ||||
|   | ||||
|     runs-on: windows-latest | ||||
|   | ||||
|     steps: | ||||
|     - uses: actions/checkout@v1 | ||||
|       name: Checkout Code | ||||
|       | ||||
|     - name: Setup MSBuild Path | ||||
|       uses: warrenbuckley/Setup-MSBuild@v1 | ||||
|       env: | ||||
|         ACTIONS_ALLOW_UNSECURE_COMMANDS: 'true' | ||||
|         | ||||
|     - name: Setup NuGet | ||||
|       uses: NuGet/setup-nuget@v1.0.2 | ||||
|       env: | ||||
|         ACTIONS_ALLOW_UNSECURE_COMMANDS: 'true' | ||||
|       | ||||
|     - name: Restore NuGet Packages | ||||
|       run: nuget restore N_m3u8DL-CLI.sln | ||||
|   | ||||
|     - name: Build  | ||||
|       run: msbuild N_m3u8DL-CLI.sln /p:Configuration=Release /p:DebugSymbols=false /p:DebugType=None | ||||
|   | ||||
|     - name: Upload Artifact | ||||
|       uses: actions/upload-artifact@v1.0.0 | ||||
|       with: | ||||
|         name: N_m3u8DL-CLI_latest | ||||
|         path: N_m3u8DL-CLI\bin\Release\ | ||||
| @@ -1,12 +1,10 @@ | ||||
|  | ||||
| Microsoft Visual Studio Solution File, Format Version 12.00 | ||||
| # Visual Studio 15 | ||||
| VisualStudioVersion = 15.0.27703.2000 | ||||
| # Visual Studio Version 16 | ||||
| VisualStudioVersion = 16.0.29215.179 | ||||
| MinimumVisualStudioVersion = 10.0.40219.1 | ||||
| Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "N_m3u8DL-CLI", "N_m3u8DL-CLI\N_m3u8DL-CLI.csproj", "{4FB61439-B738-46AC-B3AF-2BF72150D057}" | ||||
| EndProject | ||||
| Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GUI-MainWindow", "GUI-MainWindow\GUI-MainWindow.csproj", "{FE91DB43-1F1F-4119-B808-A7F4795BB4D0}" | ||||
| EndProject | ||||
| Global | ||||
| 	GlobalSection(SolutionConfigurationPlatforms) = preSolution | ||||
| 		Debug|Any CPU = Debug|Any CPU | ||||
| @@ -17,10 +15,6 @@ Global | ||||
| 		{4FB61439-B738-46AC-B3AF-2BF72150D057}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||||
| 		{4FB61439-B738-46AC-B3AF-2BF72150D057}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||||
| 		{4FB61439-B738-46AC-B3AF-2BF72150D057}.Release|Any CPU.Build.0 = Release|Any CPU | ||||
| 		{FE91DB43-1F1F-4119-B808-A7F4795BB4D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||||
| 		{FE91DB43-1F1F-4119-B808-A7F4795BB4D0}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||||
| 		{FE91DB43-1F1F-4119-B808-A7F4795BB4D0}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||||
| 		{FE91DB43-1F1F-4119-B808-A7F4795BB4D0}.Release|Any CPU.Build.0 = Release|Any CPU | ||||
| 	EndGlobalSection | ||||
| 	GlobalSection(SolutionProperties) = preSolution | ||||
| 		HideSolutionNode = FALSE | ||||
|   | ||||
| @@ -2,6 +2,9 @@ | ||||
|  | ||||
| namespace N_m3u8DL_CLI | ||||
| { | ||||
|     /** | ||||
|      * https://www.cnblogs.com/linxuanchen/p/c-sharp-command-line-argument-parser.html | ||||
|      */ | ||||
|     public class CommandLineArgument | ||||
|     { | ||||
|         List<CommandLineArgument> _arguments; | ||||
|   | ||||
							
								
								
									
										318
									
								
								N_m3u8DL-CLI/Decode51CtoKey.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										318
									
								
								N_m3u8DL-CLI/Decode51CtoKey.cs
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										41
									
								
								N_m3u8DL-CLI/DecodeDdyun.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								N_m3u8DL-CLI/DecodeDdyun.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,41 @@ | ||||
| using System.Security.Cryptography; | ||||
| using System.Text; | ||||
| using System.Text.RegularExpressions; | ||||
|  | ||||
| namespace N_m3u8DL_CLI | ||||
| { | ||||
|     class DecodeDdyun | ||||
|     { | ||||
|         public static string DecryptM3u8(byte[] byteArray) | ||||
|         { | ||||
|             string tmp = DecodeNfmovies.DecryptM3u8(byteArray); | ||||
|             if (tmp.StartsWith("duoduo.key")) | ||||
|             { | ||||
|                 tmp = Regex.Replace(tmp, @"#EXT-X-BYTERANGE:.*\s", ""); | ||||
|                 tmp = tmp.Replace("https:", "jump/https:") | ||||
|                     .Replace("inews.gtimg.com", "puui.qpic.cn"); | ||||
|             } | ||||
|             return tmp; | ||||
|         } | ||||
|  | ||||
|         //https://player.ddyunp.com/jQuery.min.js?v1.5 | ||||
|         public static string GetVaildM3u8Url(string url) | ||||
|         { | ||||
|             //url: https://hls.ddyunp.com/ddyun/id/1/key/playlist.m3u8 | ||||
|             string id = Regex.Match(url, @"\w{20,}").Value; | ||||
|             string tm = Global.GetTimeStamp(false); | ||||
|             string t = ((long.Parse(tm) / 0x186a0) * 0x64).ToString(); | ||||
|             string tmp = id + "duoduo" + "1" + t; | ||||
|             MD5 md5 = MD5.Create(); | ||||
|             byte[] bs = Encoding.UTF8.GetBytes(tmp); | ||||
|             byte[] hs = md5.ComputeHash(bs); | ||||
|             StringBuilder sb = new StringBuilder(); | ||||
|             foreach (byte b in hs) | ||||
|             { | ||||
|                 sb.Append(b.ToString("x2")); | ||||
|             } | ||||
|             string key = sb.ToString(); | ||||
|             return Regex.Replace(url, @"1/\w{20,}", "1/" + key); | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										203
									
								
								N_m3u8DL-CLI/DecodeImooc.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										203
									
								
								N_m3u8DL-CLI/DecodeImooc.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,203 @@ | ||||
| using NiL.JS.BaseLibrary; | ||||
| using NiL.JS.Core; | ||||
| using NiL.JS.Extensions; | ||||
| using System; | ||||
| using Array = System.Array; | ||||
|  | ||||
| namespace N_m3u8DL_CLI | ||||
| { | ||||
|     /* | ||||
|      * js代码来自:https://www.imooc.com/static/moco/player/3.0.6.3/mocoplayer.js?v=202006122046 | ||||
|      *  | ||||
|      */ | ||||
|     class DecodeImooc | ||||
|     { | ||||
|         private static string JS = @" | ||||
| function n(t, e) { | ||||
|                 function r(t, e) { | ||||
|                     var r = ''; | ||||
|                     if ('object' == typeof t) | ||||
|                         for (var n = 0; n < t.length; n++) | ||||
|                             r += String.fromCharCode(t[n]); | ||||
|                     t = r || t; | ||||
|                     for (var i, o, a = new Uint8Array(t.length), s = e.length, n = 0; n < t.length; n++) | ||||
|                         o = n % s, | ||||
|                         i = t[n], | ||||
|                         i = i.toString().charCodeAt(0), | ||||
|                         a[n] = i ^ e.charCodeAt(o); | ||||
|                     return a | ||||
|                 } | ||||
|                 function n(t) { | ||||
|                     var e = ''; | ||||
|                     if ('object' == typeof t) | ||||
|                         for (var r = 0; r < t.length; r++) | ||||
|                             e += String.fromCharCode(t[r]); | ||||
|                     t = e || t; | ||||
|                     var n = new Uint8Array(t.length); | ||||
|                     for (r = 0; r < t.length; r++) | ||||
|                         n[r] = t[r].toString().charCodeAt(0); | ||||
|                     var i, o, r = 0; | ||||
|                     for (r = 0; r < n.length; r++) | ||||
|                         0 != (i = n[r] % 3) && r + i < n.length && (o = n[r + 1], | ||||
|                         n[r + 1] = n[r + i], | ||||
|                         n[r + i] = o, | ||||
|                         r = r + i + 1); | ||||
|                     return n | ||||
|                 } | ||||
|                 function i(t) { | ||||
|                     var e = ''; | ||||
|                     if ('object' == typeof t) | ||||
|                         for (var r = 0; r < t.length; r++) | ||||
|                             e += String.fromCharCode(t[r]); | ||||
|                     t = e || t; | ||||
|                     var n = new Uint8Array(t.length); | ||||
|                     for (r = 0; r < t.length; r++) | ||||
|                         n[r] = t[r].toString().charCodeAt(0); | ||||
|                     var r = 0 | ||||
|                       , i = 0 | ||||
|                       , o = 0 | ||||
|                       , a = 0; | ||||
|                     for (r = 0; r < n.length; r++) | ||||
|                         o = n[r] % 2, | ||||
|                         o && r++, | ||||
|                         a++; | ||||
|                     var s = new Uint8Array(a); | ||||
|                     for (r = 0; r < n.length; r++) | ||||
|                         o = n[r] % 2, | ||||
|                         s[i++] = o ? n[r++] : n[r]; | ||||
|                     return s | ||||
|                 } | ||||
|                 function o(t, e) { | ||||
|                     var r = 0 | ||||
|                       , n = 0 | ||||
|                       , i = 0 | ||||
|                       , o = 0 | ||||
|                       , a = ''; | ||||
|                     if ('object' == typeof t) | ||||
|                         for (var r = 0; r < t.length; r++) | ||||
|                             a += String.fromCharCode(t[r]); | ||||
|                     t = a || t; | ||||
|                     var s = new Uint8Array(t.length); | ||||
|                     for (r = 0; r < t.length; r++) | ||||
|                         s[r] = t[r].toString().charCodeAt(0); | ||||
|                     for (r = 0; r < t.length; r++) | ||||
|                         if (0 != (o = s[r] % 5) && 1 != o && r + o < s.length && (i = s[r + 1], | ||||
|                         n = r + 2, | ||||
|                         s[r + 1] = s[r + o], | ||||
|                         s[o + r] = i, | ||||
|                         (r = r + o + 1) - 2 > n)) | ||||
|                             for (; n < r - 2; n++) | ||||
|                                 s[n] = s[n] ^ e.charCodeAt(n % e.length); | ||||
|                     for (r = 0; r < t.length; r++) | ||||
|                         s[r] = s[r] ^ e.charCodeAt(r % e.length); | ||||
|                     return s | ||||
|                 } | ||||
|                 for (var a = { | ||||
|                     data: { | ||||
|                         info: t | ||||
|                     } | ||||
|                 }, s = { | ||||
|                     q: r, | ||||
|                     h: n, | ||||
|                     m: i, | ||||
|                     k: o | ||||
|                 }, l = a.data.info, u = l.substring(l.length - 4).split(''), c = 0; c < u.length; c++) | ||||
|                     u[c] = u[c].toString().charCodeAt(0) % 4; | ||||
|                 u.reverse(); | ||||
|                 for (var d = [], c = 0; c < u.length; c++) | ||||
|                     d.push(l.substring(u[c] + 1, u[c] + 2)), | ||||
|                     l = l.substring(0, u[c] + 1) + l.substring(u[c] + 2); | ||||
|                 a.data.encrypt_table = d, | ||||
|                 a.data.key_table = []; | ||||
|                 for (var c in a.data.encrypt_table) | ||||
|                     'q' != a.data.encrypt_table[c] && 'k' != a.data.encrypt_table[c] || (a.data.key_table.push(l.substring(l.length - 12)), | ||||
|                     l = l.substring(0, l.length - 12)); | ||||
|                 a.data.key_table.reverse(), | ||||
|                 a.data.info = l; | ||||
|                 var f = new Array(-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,62,-1,-1,-1,63,52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-1,-1,-1,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1,-1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,-1,-1,-1,-1,-1); | ||||
|                 a.data.info = function(t) { | ||||
|                     var e, r, n, i, o, a, s; | ||||
|                     for (a = t.length, | ||||
|                     o = 0, | ||||
|                     s = ''; o < a; ) { | ||||
|                         do { | ||||
|                             e = f[255 & t.charCodeAt(o++)] | ||||
|                         } while (o < a && -1 == e);if (-1 == e) | ||||
|                             break; | ||||
|                         do { | ||||
|                             r = f[255 & t.charCodeAt(o++)] | ||||
|                         } while (o < a && -1 == r);if (-1 == r) | ||||
|                             break; | ||||
|                         s += String.fromCharCode(e << 2 | (48 & r) >> 4); | ||||
|                         do { | ||||
|                             if (61 == (n = 255 & t.charCodeAt(o++))) | ||||
|                                 return s; | ||||
|                             n = f[n] | ||||
|                         } while (o < a && -1 == n);if (-1 == n) | ||||
|                             break; | ||||
|                         s += String.fromCharCode((15 & r) << 4 | (60 & n) >> 2); | ||||
|                         do { | ||||
|                             if (61 == (i = 255 & t.charCodeAt(o++))) | ||||
|                                 return s; | ||||
|                             i = f[i] | ||||
|                         } while (o < a && -1 == i);if (-1 == i) | ||||
|                             break; | ||||
|                         s += String.fromCharCode((3 & n) << 6 | i) | ||||
|                     } | ||||
|                     return s | ||||
|                 }(a.data.info); | ||||
|                 for (var c in a.data.encrypt_table) { | ||||
|                     var h = a.data.encrypt_table[c]; | ||||
|                     if ('q' == h || 'k' == h) { | ||||
|                         var p = a.data.key_table.pop(); | ||||
|                         a.data.info = s[a.data.encrypt_table[c]](a.data.info, p) | ||||
|                     } else | ||||
|                         a.data.info = s[a.data.encrypt_table[c]](a.data.info) | ||||
|                 } | ||||
|                 if (e) | ||||
|                     return a.data.info; | ||||
|                 var g = ''; | ||||
|                 for (c = 0; c < a.data.info.length; c++) | ||||
|                     g += String.fromCharCode(a.data.info[c]); | ||||
|                 return g | ||||
|             } | ||||
|             function Uint8ArrayToString(fileData){ | ||||
|               var dataString = ''; | ||||
|               for (var i = 0; i < fileData.length; i++) { | ||||
|                 dataString += Number(fileData[i]) + ','; | ||||
|               } | ||||
|               return dataString; | ||||
|             } | ||||
|             function decodeKey(resp){ | ||||
|                 var string = eval('('+resp+')'); | ||||
|                 //return btoa(String.fromCharCode.apply(null, new Uint8Array(n(string.data.info, 1)))); | ||||
|                 return Uint8ArrayToString(new Uint8Array(n(string.data.info, 1))); | ||||
|             } | ||||
|             function decodeM3u8(resp){ | ||||
|                 var string = eval('('+resp+')'); | ||||
|                 return n(string.data.info); | ||||
|             } | ||||
|             "; | ||||
|  | ||||
|  | ||||
|         public static string DecodeM3u8(string resp) | ||||
|         { | ||||
|             var context = new Context(); | ||||
|             context.Eval(JS); | ||||
|             var concatFunction = context.GetVariable("decodeM3u8").As<Function>(); | ||||
|             string m3u8 = concatFunction.Call(new Arguments { resp }).ToString(); | ||||
|             return m3u8; | ||||
|         } | ||||
|  | ||||
|         public static string DecodeKey(string resp) | ||||
|         { | ||||
|             var context = new Context(); | ||||
|             context.Eval(JS); | ||||
|             var concatFunction = context.GetVariable("decodeKey").As<Function>(); | ||||
|             string key = concatFunction.Call(new Arguments { resp }).ToString(); | ||||
|             byte[] v = Array.ConvertAll(key.Trim(',').Split(','), s => (byte)int.Parse(s)); | ||||
|             string realKey = Convert.ToBase64String(v); | ||||
|             return realKey; | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										36
									
								
								N_m3u8DL-CLI/DecodeNfmovies.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								N_m3u8DL-CLI/DecodeNfmovies.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,36 @@ | ||||
| using System; | ||||
| using System.IO; | ||||
| using System.Linq; | ||||
| using System.Text; | ||||
|  | ||||
| namespace N_m3u8DL_CLI | ||||
| { | ||||
|     class DecodeNfmovies | ||||
|     { | ||||
|         //https://jx.nfmovies.com/hls.min.js | ||||
|         public static string DecryptM3u8(byte[] byteArray) | ||||
|         { | ||||
|             var t = byteArray; | ||||
|             var decrypt = ""; | ||||
|             if (137 == t[0] && 80 == t[1] && 130 == t[354] && 96 == t[353]) t = t.Skip(355).ToArray(); | ||||
|             else | ||||
|             { | ||||
|                 if (137 != t[0] || 80 != t[1] || 130 != t[394] || 96 != t[393]) | ||||
|                 { | ||||
|                     for (var i = 0; i < t.Length; i++) decrypt += Convert.ToChar(t[i]); | ||||
|                     return decrypt; | ||||
|                 } | ||||
|                 t = t.Skip(395).ToArray(); | ||||
|             } | ||||
|             using (var zipStream = | ||||
|                 new System.IO.Compression.GZipStream(new MemoryStream(t), System.IO.Compression.CompressionMode.Decompress)) | ||||
|             { | ||||
|                 using (StreamReader sr = new StreamReader(zipStream, Encoding.UTF8)) | ||||
|                 { | ||||
|                     decrypt = sr.ReadToEnd(); | ||||
|                 } | ||||
|             } | ||||
|             return decrypt; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -10,7 +10,7 @@ namespace N_m3u8DL_CLI | ||||
| { | ||||
|     class Decrypter | ||||
|     { | ||||
|         public static byte[] AES128Decrypt(string filePath, byte[] keyByte, byte[] ivByte) | ||||
|         public static byte[] AES128Decrypt(string filePath, byte[] keyByte, byte[] ivByte, CipherMode mode = CipherMode.CBC) | ||||
|         { | ||||
|             FileStream fs = new FileStream(filePath, FileMode.Open); | ||||
|             //获取文件大小 | ||||
| @@ -19,12 +19,12 @@ namespace N_m3u8DL_CLI | ||||
|             fs.Read(inBuff, 0, inBuff.Length); | ||||
|             fs.Close(); | ||||
|  | ||||
|             Aes dcpt = Aes.Create("AES"); | ||||
|             Aes dcpt = Aes.Create(); | ||||
|             dcpt.BlockSize = 128; | ||||
|             dcpt.KeySize = 128; | ||||
|             dcpt.Key = keyByte; | ||||
|             dcpt.IV = ivByte; | ||||
|             dcpt.Mode = CipherMode.CBC; | ||||
|             dcpt.Mode = mode; | ||||
|             dcpt.Padding = PaddingMode.PKCS7; | ||||
|  | ||||
|             ICryptoTransform cTransform = dcpt.CreateDecryptor(); | ||||
| @@ -32,16 +32,16 @@ namespace N_m3u8DL_CLI | ||||
|             return resultArray; | ||||
|         } | ||||
|  | ||||
|         public static byte[] AES128Decrypt(byte[] encryptedBuff, byte[] keyByte, byte[] ivByte) | ||||
|         public static byte[] AES128Decrypt(byte[] encryptedBuff, byte[] keyByte, byte[] ivByte, CipherMode mode = CipherMode.CBC) | ||||
|         { | ||||
|             byte[] inBuff = encryptedBuff; | ||||
|  | ||||
|             Aes dcpt = Aes.Create("AES"); | ||||
|             Aes dcpt = Aes.Create(); | ||||
|             dcpt.BlockSize = 128; | ||||
|             dcpt.KeySize = 128; | ||||
|             dcpt.Key = keyByte; | ||||
|             dcpt.IV = ivByte; | ||||
|             dcpt.Mode = CipherMode.CBC; | ||||
|             dcpt.Mode = mode; | ||||
|             dcpt.Padding = PaddingMode.PKCS7; | ||||
|  | ||||
|             ICryptoTransform cTransform = dcpt.CreateDecryptor(); | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -72,43 +72,55 @@ namespace N_m3u8DL_CLI | ||||
|                 { | ||||
|                     IsDone = false;  //设置为未完成下载 | ||||
|  | ||||
|                     if (Method == "NONE") | ||||
|                     if (Method == "NONE" || method.Contains("NOTSUPPORTED"))  | ||||
|                     { | ||||
|                         LOGGER.PrintLine("<" + SegIndex + " Downloading>"); | ||||
|                         LOGGER.WriteLine("<" + SegIndex + " Downloading>"); | ||||
|                         byte[] segBuff = Global.HttpDownloadFileToBytes(fileUrl, Headers, TimeOut); | ||||
|                         //byte[] segBuff = Global.WebClientDownloadToBytes(fileUrl, Headers); | ||||
|                         Global.AppendBytesToFileStreamAndDoNotClose(LiveStream, segBuff); | ||||
|                         LOGGER.PrintLine("<" + SegIndex + " Complete>\r\n"); | ||||
|                         LOGGER.WriteLine("<" + SegIndex + " Complete>"); | ||||
|                         IsDone = true; | ||||
|                     } | ||||
|                     else if (Method == "AES-128") | ||||
|                     { | ||||
|                         LOGGER.PrintLine("<" + SegIndex + " Downloading>"); | ||||
|                         LOGGER.WriteLine("<" + SegIndex + " Downloading>"); | ||||
|                         byte[] encryptedBuff = Global.HttpDownloadFileToBytes(fileUrl, Headers, TimeOut); | ||||
|                         //byte[] encryptedBuff = Global.WebClientDownloadToBytes(fileUrl, Headers); | ||||
|                         byte[] decryptBuff = Decrypter.AES128Decrypt( | ||||
|                         byte[] decryptBuff = null; | ||||
|                         decryptBuff = Decrypter.AES128Decrypt( | ||||
|                             encryptedBuff, | ||||
|                             Convert.FromBase64String(Key), | ||||
|                             Decrypter.HexStringToBytes(Iv) | ||||
|                             ); | ||||
|                         Global.AppendBytesToFileStreamAndDoNotClose(LiveStream, decryptBuff); | ||||
|                         LOGGER.PrintLine("<" + SegIndex + " Complete>\r\n"); | ||||
|                         LOGGER.WriteLine("<" + SegIndex + " Complete>"); | ||||
|                         IsDone = true; | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|                         LOGGER.PrintLine("不支持这种加密方式!", LOGGER.Error); | ||||
|                         //LOGGER.PrintLine("不支持这种加密方式!", LOGGER.Error); | ||||
|                         IsDone = true; | ||||
|                     } | ||||
|                     if (firstSeg && Global.FileSize(LiveFile) != 0) | ||||
|                     { | ||||
|                         LOGGER.STOPLOG = false;  //记录日志 | ||||
|                         //LOGGER.STOPLOG = false;  //记录日志 | ||||
|                         foreach (string ss in (string[])Global.GetVideoInfo(LiveFile).ToArray(typeof(string))) | ||||
|                         { | ||||
|                             LOGGER.WriteLine(ss.Trim()); | ||||
|                         } | ||||
|                         firstSeg = false; | ||||
|                         LOGGER.STOPLOG = true;  //停止记录日志 | ||||
|                         //LOGGER.STOPLOG = true;  //停止记录日志 | ||||
|                     } | ||||
|                     HLSLiveDownloader.REC_DUR += SegDur; | ||||
|                     if (HLSLiveDownloader.REC_DUR_LIMIT != -1 && HLSLiveDownloader.REC_DUR >= HLSLiveDownloader.REC_DUR_LIMIT)  | ||||
|                     { | ||||
|                         LOGGER.PrintLine(strings.recordLimitReached, LOGGER.Warning); | ||||
|                         LOGGER.WriteLine(strings.recordLimitReached); | ||||
|                         Environment.Exit(0); //正常退出 | ||||
|                     } | ||||
|                     return; | ||||
|                 } | ||||
| @@ -167,7 +179,7 @@ namespace N_m3u8DL_CLI | ||||
|                 if (File.Exists(savePath) && Global.ShouldStop == false)  | ||||
|                 { | ||||
|                     FileInfo fi = new FileInfo(savePath); | ||||
|                     if (Method == "NONE") | ||||
|                     if (Method == "NONE" || method.Contains("NOTSUPPORTED")) | ||||
|                     { | ||||
|                         fi.MoveTo(Path.GetDirectoryName(savePath) + "\\" + Path.GetFileNameWithoutExtension(savePath) + ".ts"); | ||||
|                         DownloadManager.DownloadedSize += fi.Length; | ||||
| @@ -179,11 +191,24 @@ namespace N_m3u8DL_CLI | ||||
|                         //解密 | ||||
|                         try | ||||
|                         { | ||||
|                             byte[] decryptBuff = Decrypter.AES128Decrypt( | ||||
|                             byte[] decryptBuff = null; | ||||
|                             if(fileUrl.Contains(".51cto.com/")) //使用AES-128-ECB模式解密 | ||||
|                             { | ||||
|                                 decryptBuff = Decrypter.AES128Decrypt( | ||||
|                                     fi.FullName, | ||||
|                                     Convert.FromBase64String(Key), | ||||
|                                     Decrypter.HexStringToBytes(Iv), | ||||
|                                     System.Security.Cryptography.CipherMode.ECB | ||||
|                                     ); | ||||
|                             } | ||||
|                             else | ||||
|                             { | ||||
|                                 decryptBuff = Decrypter.AES128Decrypt( | ||||
|                                     fi.FullName, | ||||
|                                     Convert.FromBase64String(Key), | ||||
|                                     Decrypter.HexStringToBytes(Iv) | ||||
|                                     ); | ||||
|                             } | ||||
|                             FileStream fs = new FileStream(Path.GetDirectoryName(savePath) + "\\" + Path.GetFileNameWithoutExtension(savePath) + ".ts", FileMode.Create); | ||||
|                             fs.Write(decryptBuff, 0, decryptBuff.Length); | ||||
|                             fs.Close(); | ||||
| @@ -193,20 +218,16 @@ namespace N_m3u8DL_CLI | ||||
|                         } | ||||
|                         catch (Exception ex) | ||||
|                         { | ||||
|                             LOGGER.PrintLine(ex.Message, LOGGER.Error); | ||||
|                             LOGGER.WriteLineError(ex.Message); | ||||
|                             Thread.Sleep(3000); | ||||
|                             Environment.Exit(-1); | ||||
|                         } | ||||
|                     } | ||||
|                     else if(File.Exists(fi.FullName) | ||||
|                         && Method != "AES-128") | ||||
|                     { | ||||
|                         LOGGER.WriteLineError($"Do not support this METHOD: {Method}"); | ||||
|                         LOGGER.PrintLine("不支持这种加密方式!", LOGGER.Error); | ||||
|                         return; | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|                         LOGGER.WriteLineError("Something was wrong!"); | ||||
|                         LOGGER.PrintLine("遇到了某些错误!", LOGGER.Error); | ||||
|                         LOGGER.WriteLineError(strings.SomethingWasWrong); | ||||
|                         LOGGER.PrintLine(strings.SomethingWasWrong, LOGGER.Error); | ||||
|                         return; | ||||
|                     } | ||||
|                     return; | ||||
| @@ -215,14 +236,14 @@ namespace N_m3u8DL_CLI | ||||
|             catch (Exception ex) | ||||
|             { | ||||
|                 LOGGER.WriteLineError(ex.Message); | ||||
|                 if (ex.Message.Contains("404")) | ||||
|                 if (ex.Message.Contains("404") || ex.Message.Contains("400"))//(400) 错误的请求,片段过期会提示400错误 | ||||
|                 { | ||||
|                     IsDone = true; | ||||
|                     return; | ||||
|                 } | ||||
|                 else if (IsLive && count++ < Retry)  | ||||
|                 { | ||||
|                     Thread.Sleep(5000); | ||||
|                     Thread.Sleep(2000);//直播一般3-6秒一个片段 | ||||
|                     Down(); | ||||
|                 } | ||||
|             } | ||||
|   | ||||
| @@ -10,19 +10,27 @@ namespace N_m3u8DL_CLI | ||||
| { | ||||
|     class FFmpeg | ||||
|     { | ||||
|         private static string outPutPath = string.Empty; | ||||
|         private static string reportFile = string.Empty; | ||||
|         private static bool useAACFilter = false;  //是否启用滤镜 | ||||
|         private static bool writeDate = true;  //是否写入录制日期 | ||||
|         public static string OutPutPath { get => outPutPath; set => outPutPath = value; } | ||||
|         public static string ReportFile { get => reportFile; set => reportFile = value; } | ||||
|         public static bool UseAACFilter { get => useAACFilter; set => useAACFilter = value; } | ||||
|         public static bool WriteDate { get => writeDate; set => writeDate = value; } | ||||
|         public static string FFMPEG_PATH = "ffmpeg"; | ||||
|         public static string REC_TIME = ""; //录制日期 | ||||
|  | ||||
|         public static string OutPutPath { get; set; } = string.Empty; | ||||
|         public static string ReportFile { get; set; } = string.Empty; | ||||
|         public static bool UseAACFilter { get; set; } = false;  //是否启用滤镜 | ||||
|         public static bool WriteDate { get; set; } = true;  //是否写入录制日期 | ||||
|  | ||||
|         public static void Merge(string[] files, string muxFormat, bool fastStart, | ||||
|             string poster = "", string audioName = "", string title = "", | ||||
|             string copyright = "", string comment = "", string encodingTool = "") | ||||
|         { | ||||
|             string dateString = string.IsNullOrEmpty(REC_TIME) ? DateTime.Now.ToString("o") : REC_TIME; | ||||
|  | ||||
|             //同名文件已存在的共存策略 | ||||
|             if (File.Exists($"{OutPutPath}.{muxFormat.ToLower()}"))  | ||||
|             { | ||||
|                 OutPutPath = Path.Combine(Path.GetDirectoryName(OutPutPath), | ||||
|                     Path.GetFileName(OutPutPath) + "_" + DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss")); | ||||
|             } | ||||
|  | ||||
|             string command = "-loglevel warning -i concat:\""; | ||||
|             string data = string.Empty; | ||||
|             string ddpAudio = string.Empty; | ||||
| @@ -43,7 +51,7 @@ namespace N_m3u8DL_CLI | ||||
|                     command += " " + (string.IsNullOrEmpty(ddpAudio) ? "" : "-i \"" + ddpAudio + "\""); | ||||
|                     command += | ||||
|                         $" -map 0:v? {(string.IsNullOrEmpty(ddpAudio) ? "-map 0:a?" : $"-map {(string.IsNullOrEmpty(poster) ? "1" : "2")}:a -map 0:a?")} -map 0:s? " + (string.IsNullOrEmpty(poster) ? "" : addPoster) | ||||
|                         + (writeDate ? " -metadata date=\"" + DateTime.Now.ToString("o") + "\"" : "") + | ||||
|                         + (WriteDate ? " -metadata date=\"" + dateString + "\"" : "") + | ||||
|                         " -metadata encoding_tool=\"" + encodingTool + "\" -metadata title=\"" + title + | ||||
|                         "\" -metadata copyright=\"" + copyright + "\" -metadata comment=\"" + comment + | ||||
|                         $"\" -metadata:s:a:{(string.IsNullOrEmpty(ddpAudio) ? "0" : "1")} handler_name=\"" + audioName + $"\" -metadata:s:a:{(string.IsNullOrEmpty(ddpAudio) ? "0" : "1")} handler=\"" + audioName + "\" "; | ||||
| @@ -76,8 +84,8 @@ namespace N_m3u8DL_CLI | ||||
|  | ||||
|             } | ||||
|  | ||||
|             Run("ffmpeg", command, Path.GetDirectoryName(files[0])); | ||||
|             LOGGER.WriteLine("Result in [ffreport.log]"); | ||||
|             Run(FFMPEG_PATH, command, Path.GetDirectoryName(files[0])); | ||||
|             LOGGER.WriteLine(strings.ffmpegDone); | ||||
|             //Console.WriteLine(command); | ||||
|         } | ||||
|  | ||||
| @@ -85,8 +93,8 @@ namespace N_m3u8DL_CLI | ||||
|         { | ||||
|             if (Global.VIDEO_TYPE == "H264") | ||||
|             { | ||||
|                 Run("ffmpeg", | ||||
|                     "-loglevel quiet -i \"" + file + "\" -map 0 -c copy -f mpegts -bsf:v h264_mp4toannexb \"" | ||||
|                 Run(FFMPEG_PATH, | ||||
|                     "-loglevel quiet -i \"" + file + "\" -map 0 -c copy -copy_unknown -f mpegts -bsf:v h264_mp4toannexb \"" | ||||
|                     + Path.GetFileNameWithoutExtension(file) + "[MPEGTS].ts\"",  | ||||
|                     Path.GetDirectoryName(file)); | ||||
|                 if (File.Exists(Path.GetDirectoryName(file) + "\\" + Path.GetFileNameWithoutExtension(file) + "[MPEGTS].ts")) | ||||
| @@ -97,8 +105,8 @@ namespace N_m3u8DL_CLI | ||||
|             } | ||||
|             else if (Global.VIDEO_TYPE == "H265") | ||||
|             { | ||||
|                 Run("ffmpeg", | ||||
|                     "-loglevel quiet -i \"" + file + "\" -map 0 -c copy -f mpegts -bsf:v hevc_mp4toannexb \"" | ||||
|                 Run(FFMPEG_PATH, | ||||
|                     "-loglevel quiet -i \"" + file + "\" -map 0 -c copy -copy_unknown -f mpegts -bsf:v hevc_mp4toannexb \"" | ||||
|                     + Path.GetFileNameWithoutExtension(file) + "[MPEGTS].ts\"", | ||||
|                     Path.GetDirectoryName(file)); | ||||
|                 if (File.Exists(Path.GetDirectoryName(file) + "\\" + Path.GetFileNameWithoutExtension(file) + "[MPEGTS].ts")) | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -12,15 +12,17 @@ namespace N_m3u8DL_CLI | ||||
| { | ||||
|     class HLSLiveDownloader | ||||
|     { | ||||
|         public static int REC_DUR_LIMIT = -1; //默认不限制录制时长 | ||||
|         public static double REC_DUR = 0; //已录制时长 | ||||
|         private string liveFile = string.Empty; | ||||
|         private string jsonFile = string.Empty; | ||||
|         private string headers = string.Empty; | ||||
|         private string downDir = string.Empty; | ||||
|         private FileStream liveStream = null; | ||||
|         private int targetduration = 10; | ||||
|         private double targetduration = 10; | ||||
|         private bool isFirstJson = true; | ||||
|  | ||||
|  | ||||
|         public double TotalDuration { get; set; } | ||||
|         public string Headers { get => headers; set => headers = value; } | ||||
|         public string DownDir { get => downDir; set => downDir = value; } | ||||
|         public FileStream LiveStream { get => liveStream; set => liveStream = value; } | ||||
| @@ -33,7 +35,7 @@ namespace N_m3u8DL_CLI | ||||
|         public void TimerStart() | ||||
|         { | ||||
|             timer.Enabled = true; | ||||
|             timer.Interval = (targetduration - 2) * 1000; //执行间隔时间,单位为毫秒 | ||||
|             //timer.Interval = (targetduration - 2) * 1000; //执行间隔时间,单位为毫秒 | ||||
|             timer.Start(); | ||||
|             timer.Elapsed += new ElapsedEventHandler(UpdateList); | ||||
|             UpdateList(timer, new EventArgs());  //立即执行一次 | ||||
| @@ -57,7 +59,9 @@ namespace N_m3u8DL_CLI | ||||
|             string jsonContent = File.ReadAllText(jsonFile); | ||||
|             JObject initJson = JObject.Parse(jsonContent); | ||||
|             string m3u8Url = initJson["m3u8"].Value<string>(); | ||||
|             targetduration = initJson["m3u8Info"]["targetDuration"].Value<int>(); | ||||
|             targetduration = initJson["m3u8Info"]["targetDuration"].Value<double>(); | ||||
|             TotalDuration = initJson["m3u8Info"]["totalDuration"].Value<double>(); | ||||
|             timer.Interval = (TotalDuration - targetduration) * 1000;//设置定时器运行间隔 | ||||
|             JArray lastSegments = JArray.Parse(initJson["m3u8Info"]["segments"][0].ToString().Trim());  //上次的分段,用于比对新分段 | ||||
|             ArrayList tempList = new ArrayList();  //所有待下载的列表 | ||||
|             tempList.Clear(); | ||||
| @@ -76,6 +80,7 @@ namespace N_m3u8DL_CLI | ||||
|             Parser parser = new Parser(); | ||||
|             parser.DownDir = Path.GetDirectoryName(jsonFile); | ||||
|             parser.M3u8Url = m3u8Url; | ||||
|             parser.LiveStream = true; | ||||
|             parser.Parse();  //产生新的json文件 | ||||
|  | ||||
|             jsonContent = File.ReadAllText(jsonFile); | ||||
| @@ -89,6 +94,8 @@ namespace N_m3u8DL_CLI | ||||
|                     //Console.WriteLine(seg.ToString()); | ||||
|                 } | ||||
|             } | ||||
|             if (toDownList.Count > 0) | ||||
|                 Record(); | ||||
|         } | ||||
|  | ||||
|         //public void TryDownload() | ||||
| @@ -108,10 +115,9 @@ namespace N_m3u8DL_CLI | ||||
|  | ||||
|         private void Record() | ||||
|         { | ||||
|             ArrayList temp = toDownList; | ||||
|             while(temp.Count != 0) | ||||
|             while (toDownList.Count > 0 && (sd.FileUrl != "" ? sd.IsDone : true))  | ||||
|             { | ||||
|                 JObject info = JObject.Parse(temp[0].ToString()); | ||||
|                 JObject info = JObject.Parse(toDownList[0].ToString()); | ||||
|                 int index = info["index"].Value<int>(); | ||||
|                 sd.FileUrl = info["segUri"].Value<string>(); | ||||
|                 sd.Method = info["method"].Value<string>(); | ||||
| @@ -120,22 +126,20 @@ namespace N_m3u8DL_CLI | ||||
|                     sd.Key = info["key"].Value<string>(); | ||||
|                     sd.Iv = info["iv"].Value<string>(); | ||||
|                 } | ||||
|                 sd.TimeOut = 60000; | ||||
|                 sd.TimeOut = (int)timer.Interval - 1000;//超时时间不超过下次执行时间 | ||||
|                 sd.SegIndex = index; | ||||
|                 sd.Headers = Headers; | ||||
|                 sd.SegDur = info["duration"].Value<double>(); | ||||
|                 sd.IsLive = true;  //标记为直播 | ||||
|                 sd.LiveFile = LiveFile; | ||||
|                 sd.LiveStream = LiveStream; | ||||
|                 sd.Down();  //开始下载 | ||||
|                 while (sd.IsDone != true) ;  //忙等待 | ||||
|                 while (sd.IsDone != true) { Thread.Sleep(1); };  //忙等待 Thread.Sleep(1) 可防止cpu 100% 防止电脑风扇狂转 | ||||
|                 if (toDownList.Count > 0) | ||||
|                     toDownList.RemoveAt(0);  //下完删除一项 | ||||
|             } | ||||
|             LOGGER.PrintLine("Waiting..."); | ||||
|             //不断查找是否有新分段,有的话立即开始下载 | ||||
|             while (isNewSeg() != true) | ||||
|                 isNewSeg(); | ||||
|             Record(); | ||||
|             LOGGER.PrintLine("Waiting...", LOGGER.Warning); | ||||
|             LOGGER.WriteLine("Waiting..."); | ||||
|         } | ||||
|  | ||||
|         //检测是否有新分片 | ||||
|   | ||||
| @@ -61,6 +61,11 @@ namespace N_m3u8DL_CLI | ||||
|         { | ||||
|             try | ||||
|             { | ||||
|                 if (CursorIndex > 1000) | ||||
|                 { | ||||
|                     Console.Clear(); | ||||
|                     CursorIndex = 0; | ||||
|                 } | ||||
|                 if (cursorIndex == 0) | ||||
|                     Console.SetCursorPosition(0, CursorIndex++); | ||||
|                 else | ||||
|   | ||||
							
								
								
									
										719
									
								
								N_m3u8DL-CLI/MPDParser.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										719
									
								
								N_m3u8DL-CLI/MPDParser.cs
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1,5 +1,6 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | ||||
|   <Import Project="..\packages\Costura.Fody.4.1.0\build\Costura.Fody.props" Condition="Exists('..\packages\Costura.Fody.4.1.0\build\Costura.Fody.props')" /> | ||||
|   <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> | ||||
|   <PropertyGroup> | ||||
|     <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> | ||||
| @@ -12,6 +13,8 @@ | ||||
|     <FileAlignment>512</FileAlignment> | ||||
|     <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects> | ||||
|     <TargetFrameworkProfile /> | ||||
|     <NuGetPackageImportStamp> | ||||
|     </NuGetPackageImportStamp> | ||||
|   </PropertyGroup> | ||||
|   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> | ||||
|     <PlatformTarget>x86</PlatformTarget> | ||||
| @@ -38,9 +41,16 @@ | ||||
|     <ApplicationIcon>logo_3Iv_icon.ico</ApplicationIcon> | ||||
|   </PropertyGroup> | ||||
|   <ItemGroup> | ||||
|     <Reference Include="Costura, Version=4.1.0.0, Culture=neutral, PublicKeyToken=9919ef960d84173d, processorArchitecture=MSIL"> | ||||
|       <HintPath>..\packages\Costura.Fody.4.1.0\lib\net40\Costura.dll</HintPath> | ||||
|     </Reference> | ||||
|     <Reference Include="Microsoft.JScript" /> | ||||
|     <Reference Include="Newtonsoft.Json"> | ||||
|       <HintPath>..\..\HDC上传助手\HDC上传助手\bin\Debug\Newtonsoft.Json.dll</HintPath> | ||||
|     <Reference Include="netstandard, Version=2.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51" /> | ||||
|     <Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL"> | ||||
|       <HintPath>..\packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll</HintPath> | ||||
|     </Reference> | ||||
|     <Reference Include="NiL.JS, Version=2.5.1428.0, Culture=neutral, PublicKeyToken=fa941a7c2a4de689, processorArchitecture=MSIL"> | ||||
|       <HintPath>..\packages\NiL.JS.2.5.1428\lib\net45\NiL.JS.dll</HintPath> | ||||
|     </Reference> | ||||
|     <Reference Include="PresentationFramework" /> | ||||
|     <Reference Include="System" /> | ||||
| @@ -58,6 +68,10 @@ | ||||
|   <ItemGroup> | ||||
|     <Compile Include="CommandLineArgument.cs" /> | ||||
|     <Compile Include="CommandLineArgumentParser.cs" /> | ||||
|     <Compile Include="Decode51CtoKey.cs" /> | ||||
|     <Compile Include="DecodeDdyun.cs" /> | ||||
|     <Compile Include="DecodeImooc.cs" /> | ||||
|     <Compile Include="DecodeNfmovies.cs" /> | ||||
|     <Compile Include="Decrypter.cs" /> | ||||
|     <Compile Include="FFmpeg.cs" /> | ||||
|     <Compile Include="Global.cs" /> | ||||
| @@ -65,19 +79,33 @@ | ||||
|     <Compile Include="HLSTags.cs" /> | ||||
|     <Compile Include="LOGGER.cs" /> | ||||
|     <Compile Include="DownloadManager.cs" /> | ||||
|     <Compile Include="MPDParser.cs" /> | ||||
|     <Compile Include="Parser.cs" /> | ||||
|     <Compile Include="Program.cs" /> | ||||
|     <Compile Include="Properties\AssemblyInfo.cs" /> | ||||
|     <Compile Include="Downloader.cs" /> | ||||
|     <Compile Include="strings.Designer.cs"> | ||||
|       <AutoGen>True</AutoGen> | ||||
|       <DesignTime>True</DesignTime> | ||||
|       <DependentUpon>strings.resx</DependentUpon> | ||||
|     </Compile> | ||||
|     <Compile Include="strings.en-US.Designer.cs"> | ||||
|       <AutoGen>True</AutoGen> | ||||
|       <DesignTime>True</DesignTime> | ||||
|       <DependentUpon>strings.en-US.resx</DependentUpon> | ||||
|     </Compile> | ||||
|     <Compile Include="strings.zh-TW.Designer.cs"> | ||||
|       <AutoGen>True</AutoGen> | ||||
|       <DesignTime>True</DesignTime> | ||||
|       <DependentUpon>strings.zh-TW.resx</DependentUpon> | ||||
|     </Compile> | ||||
|     <Compile Include="Watcher.cs" /> | ||||
|   </ItemGroup> | ||||
|   <ItemGroup> | ||||
|     <None Include="App.config"> | ||||
|       <SubType>Designer</SubType> | ||||
|     </None> | ||||
|   </ItemGroup> | ||||
|   <ItemGroup> | ||||
|     <None Include="bin\Debug\Newtonsoft.Json.dll" /> | ||||
|     <None Include="packages.config" /> | ||||
|   </ItemGroup> | ||||
|   <ItemGroup> | ||||
|     <COMReference Include="Scripting"> | ||||
| @@ -93,5 +121,27 @@ | ||||
|   <ItemGroup> | ||||
|     <Content Include="logo_3Iv_icon.ico" /> | ||||
|   </ItemGroup> | ||||
|   <ItemGroup> | ||||
|     <EmbeddedResource Include="strings.en-US.resx"> | ||||
|       <Generator>ResXFileCodeGenerator</Generator> | ||||
|       <LastGenOutput>strings.en-US.Designer.cs</LastGenOutput> | ||||
|     </EmbeddedResource> | ||||
|     <EmbeddedResource Include="strings.resx"> | ||||
|       <Generator>ResXFileCodeGenerator</Generator> | ||||
|       <LastGenOutput>strings.Designer.cs</LastGenOutput> | ||||
|     </EmbeddedResource> | ||||
|     <EmbeddedResource Include="strings.zh-TW.resx"> | ||||
|       <Generator>ResXFileCodeGenerator</Generator> | ||||
|       <LastGenOutput>strings.zh-TW.Designer.cs</LastGenOutput> | ||||
|     </EmbeddedResource> | ||||
|   </ItemGroup> | ||||
|   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> | ||||
|   <Import Project="..\packages\Fody.6.0.0\build\Fody.targets" Condition="Exists('..\packages\Fody.6.0.0\build\Fody.targets')" /> | ||||
|   <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild"> | ||||
|     <PropertyGroup> | ||||
|       <ErrorText>这台计算机上缺少此项目引用的 NuGet 程序包。使用“NuGet 程序包还原”可下载这些程序包。有关更多信息,请参见 http://go.microsoft.com/fwlink/?LinkID=322105。缺少的文件是 {0}。</ErrorText> | ||||
|     </PropertyGroup> | ||||
|     <Error Condition="!Exists('..\packages\Fody.6.0.0\build\Fody.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Fody.6.0.0\build\Fody.targets'))" /> | ||||
|     <Error Condition="!Exists('..\packages\Costura.Fody.4.1.0\build\Costura.Fody.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Costura.Fody.4.1.0\build\Costura.Fody.props'))" /> | ||||
|   </Target> | ||||
| </Project> | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -10,7 +10,7 @@ using System.Runtime.InteropServices; | ||||
| [assembly: AssemblyConfiguration("")] | ||||
| [assembly: AssemblyCompany("nilaoda")] | ||||
| [assembly: AssemblyProduct("N_m3u8DL-CLI")] | ||||
| [assembly: AssemblyCopyright("Copyright ©  2019")] | ||||
| [assembly: AssemblyCopyright("Copyright ©  2020")] | ||||
| [assembly: AssemblyTrademark("")] | ||||
| [assembly: AssemblyCulture("")] | ||||
|  | ||||
| @@ -33,4 +33,4 @@ using System.Runtime.InteropServices; | ||||
| // 方法是按如下所示使用“*”: : | ||||
| // [assembly: AssemblyVersion("1.0.*")] | ||||
| [assembly: AssemblyVersion("1.0.0.0")] | ||||
| [assembly: AssemblyFileVersion("1.0.0.0")] | ||||
| [assembly: AssemblyFileVersion("2.7.0.0")] | ||||
|   | ||||
							
								
								
									
										304
									
								
								N_m3u8DL-CLI/changelog.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										304
									
								
								N_m3u8DL-CLI/changelog.txt
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										7
									
								
								N_m3u8DL-CLI/packages.config
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								N_m3u8DL-CLI/packages.config
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <packages> | ||||
|   <package id="Fody" version="6.0.0" targetFramework="net46" developmentDependency="true" /> | ||||
|   <package id="Costura.Fody" version="4.1.0" targetFramework="net46" /> | ||||
|   <package id="Newtonsoft.Json" version="12.0.3" targetFramework="net46" /> | ||||
|   <package id="NiL.JS" version="2.5.1428" targetFramework="net46" /> | ||||
| </packages> | ||||
							
								
								
									
										541
									
								
								N_m3u8DL-CLI/strings.Designer.cs
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										541
									
								
								N_m3u8DL-CLI/strings.Designer.cs
									
									
									
										generated
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										0
									
								
								N_m3u8DL-CLI/strings.en-US.Designer.cs
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								N_m3u8DL-CLI/strings.en-US.Designer.cs
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
								
								
									
										301
									
								
								N_m3u8DL-CLI/strings.en-US.resx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										301
									
								
								N_m3u8DL-CLI/strings.en-US.resx
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										302
									
								
								N_m3u8DL-CLI/strings.resx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										302
									
								
								N_m3u8DL-CLI/strings.resx
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										0
									
								
								N_m3u8DL-CLI/strings.zh-TW.Designer.cs
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								N_m3u8DL-CLI/strings.zh-TW.Designer.cs
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
								
								
									
										302
									
								
								N_m3u8DL-CLI/strings.zh-TW.resx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										302
									
								
								N_m3u8DL-CLI/strings.zh-TW.resx
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										62
									
								
								README_ENG.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								README_ENG.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,62 @@ | ||||
| ``` | ||||
|  | ||||
| ███╗   ██╗        ███╗   ███╗██████╗ ██╗   ██╗ █████╗ ██████╗ ██╗       ██████╗██╗     ██╗ | ||||
| ████╗  ██║        ████╗ ████║╚════██╗██║   ██║██╔══██╗██╔══██╗██║      ██╔════╝██║     ██║ | ||||
| ██╔██╗ ██║        ██╔████╔██║ █████╔╝██║   ██║╚█████╔╝██║  ██║██║█████╗██║     ██║     ██║ | ||||
| ██║╚██╗██║        ██║╚██╔╝██║ ╚═══██╗██║   ██║██╔══██╗██║  ██║██║╚════╝██║     ██║     ██║ | ||||
| ██║ ╚████║███████╗██║ ╚═╝ ██║██████╔╝╚██████╔╝╚█████╔╝██████╔╝███████╗ ╚██████╗███████╗██║ | ||||
| ╚═╝  ╚═══╝╚══════╝╚═╝     ╚═╝╚═════╝  ╚═════╝  ╚════╝ ╚═════╝ ╚══════╝  ╚═════╝╚══════╝╚═╝ | ||||
|                                                                                            | ||||
| ``` | ||||
| This is a m3u8 downloader.   | ||||
| ## Summary | ||||
| Supports:  | ||||
|   * Auto deceypt for `AES-128-CBC` | ||||
|   * `Master List` | ||||
|   * Live stream recording(`BETA`) | ||||
|   * Customize HTTP headers | ||||
|   * Auto merge clips(Binary or ffmpeg) | ||||
|   * Select save clip by `time code` or `index` | ||||
|   * Network driver on Windows OS | ||||
|   * Alternative audio/video track | ||||
|   * Mux without video track | ||||
|   * Auto use system proxy | ||||
|   * Optimization for Chinese streaming platform | ||||
|    | ||||
|      | ||||
|    | ||||
| ## GUI | ||||
|   * Easy-to-use `GUI` | ||||
|    | ||||
| ## Options | ||||
| ``` | ||||
| N_m3u8DL-CLI.exe <URL|JSON|FILE> [OPTIONS]   | ||||
|  | ||||
|     --workDir    Directory      Set work dir (Video will be here) | ||||
|     --saveName   Filename       Set save name(Exclude extention) | ||||
|     --baseUrl    BaseUrl        Set Baseurl | ||||
|     --headers    headers        Set HTTP headers,format: key:value user | split all key&value | ||||
|     --maxThreads Thread         Set max thread(default: 32) | ||||
|     --minThreads Thread         Set min thread(default: 16) | ||||
|     --retryCount Count          Set retry times(default: 15) | ||||
|     --timeOut    Sec            Set timeout for http request(second,default: 10) | ||||
|     --muxSetJson File           Set a json file for mux | ||||
|     --useKeyFile File           Use 16 bytes file as KEY for AES-128 decryption | ||||
|     --useKeyBase64 Base64String Use Base64 String as KEY for AES-128 decryption | ||||
|     --useKeyIV     HEXString    Use HEX String as IV for AES-128 decryption | ||||
|     --downloadRange Range       Set range for a video | ||||
|     --stopSpeed  Number         Speed below this, retry(KB/s) | ||||
|     --maxSpeed   Number         Set max download speed(KB/s) | ||||
|     --enableDelAfterDone        Enable delete clips after download completed | ||||
|     --enableMuxFastStart        Enable fast start for mp4 | ||||
|     --enableBinaryMerge         Enable use binary merge instead ffmpeg | ||||
|     --enableParseOnly           Enable parse mode | ||||
|     --enableAudioOnly           Enable only audio track when mux use ffmpeg | ||||
|     --disableDateInfo           Disable write date info when mux use ffmpeg | ||||
|     --noMerge                   Disable auto merge | ||||
|     --noProxy                   Disable use system proxy | ||||
|     --disableIntegrityCheck     Disable integrity check | ||||
| ``` | ||||
|    | ||||
| ## Document | ||||
|   https://nilaoda.github.io/N_m3u8DL-CLI/ | ||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user