You've already forked N_m3u8DL-CLI
mirror of
https://github.com/nilaoda/N_m3u8DL-CLI
synced 2025-09-09 09:20:52 +02:00
Compare commits
182 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
f5a9ed08a1 | ||
![]() |
6b8bfde19f | ||
![]() |
ff738f2849 | ||
![]() |
3d35c24a2e | ||
![]() |
41d7151e7e | ||
![]() |
94246ef163 | ||
![]() |
9c118631cf | ||
![]() |
2ee9ab234f | ||
![]() |
606f2184df | ||
![]() |
7dd2b6cee2 | ||
![]() |
f744aa990e | ||
![]() |
97c9f444b8 | ||
![]() |
8aac37bbe2 | ||
![]() |
b7e19ec699 | ||
![]() |
7e7c5c6ba9 | ||
![]() |
50722079ba | ||
![]() |
d529ece032 | ||
![]() |
9ed8b359a1 | ||
![]() |
a7591e3978 | ||
![]() |
094a89bc79 | ||
![]() |
9e7b603d3b | ||
![]() |
3801090928 | ||
![]() |
42c1d628d4 | ||
![]() |
ecefecd827 | ||
![]() |
4661818c1f | ||
![]() |
fa61cd136d | ||
![]() |
472fb0cf02 | ||
![]() |
28e39a94ac | ||
![]() |
a42ade64f3 | ||
![]() |
539f773e37 | ||
![]() |
d6f27cf90f | ||
![]() |
8912ee5e4b | ||
![]() |
409437b2c7 | ||
![]() |
350d3b508d | ||
![]() |
1e3f06eaae | ||
![]() |
2d4bc42d55 | ||
![]() |
68e06d3fa7 | ||
![]() |
6c3340e94e | ||
![]() |
051faa9f2b | ||
![]() |
115f9c9424 | ||
![]() |
faf67cd527 | ||
![]() |
38d1a1a2dc | ||
![]() |
12eb68d592 | ||
![]() |
0804e295e5 | ||
![]() |
847c4683cb | ||
![]() |
8c72947860 | ||
![]() |
f0b240a6ee | ||
![]() |
793cf53042 | ||
![]() |
612fc29197 | ||
![]() |
307e2389de | ||
![]() |
1c932abdc3 | ||
![]() |
314f0065c7 | ||
![]() |
59060bb74d | ||
![]() |
cab882c3a3 | ||
![]() |
9955532ce5 | ||
![]() |
7e127be8c2 | ||
![]() |
b46571a57f | ||
![]() |
da5861d907 | ||
![]() |
92bc91a1fb | ||
![]() |
439f50103e | ||
![]() |
8a95e31b2f | ||
![]() |
115b8a156a | ||
![]() |
120bcaebb5 | ||
![]() |
455d56707c | ||
![]() |
048adcf118 | ||
![]() |
fe5aa27b1c | ||
![]() |
039aa489b1 | ||
![]() |
14e80f0b06 | ||
![]() |
2256fff549 | ||
![]() |
84cfd4e138 | ||
![]() |
e70c229135 | ||
![]() |
8b520d0c19 | ||
![]() |
71d69de51a | ||
![]() |
bc89ead00d | ||
![]() |
ae79d6eb3a | ||
![]() |
96bd8af883 | ||
![]() |
89b1e30e0f | ||
![]() |
7a741359ab | ||
![]() |
564b6ad291 | ||
![]() |
a0fc9404f7 | ||
![]() |
5267be1699 | ||
![]() |
20bfda39e7 | ||
![]() |
ba4c0eeda7 | ||
![]() |
5d72e24002 | ||
![]() |
a87c051d23 | ||
![]() |
44e1b68d6b | ||
![]() |
e65dfa52cd | ||
![]() |
965c173899 | ||
![]() |
880af02cc2 | ||
![]() |
2742de43c4 | ||
![]() |
9d8cb57390 | ||
![]() |
9e2a192dab | ||
![]() |
33cf9e2256 | ||
![]() |
2959cbbb5c | ||
![]() |
c2eb8a6adc | ||
![]() |
e1b591b81c | ||
![]() |
334b1939b5 | ||
![]() |
7e916b65fd | ||
![]() |
4ead563fa2 | ||
![]() |
1b387a06e5 | ||
![]() |
6e7b4ac7ea | ||
![]() |
e98c5205d1 | ||
![]() |
d7890dd124 | ||
![]() |
82f2111522 | ||
![]() |
4c3207586f | ||
![]() |
69b411e37c | ||
![]() |
1e8525041f | ||
![]() |
65ae72d4a4 | ||
![]() |
4a4bfae5ab | ||
![]() |
d586dddfcd | ||
![]() |
fca6b3ff6c | ||
![]() |
5d75626a36 | ||
![]() |
a94271c244 | ||
![]() |
c51118dce7 | ||
![]() |
81b2e87bf7 | ||
![]() |
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 |
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\N_m3u8DL-CLI.exe
|
661
N_m3u8DL-CLI/CSChaCha20.cs
Normal file
661
N_m3u8DL-CLI/CSChaCha20.cs
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,80 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace N_m3u8DL_CLI
|
||||
{
|
||||
/**
|
||||
* https://www.cnblogs.com/linxuanchen/p/c-sharp-command-line-argument-parser.html
|
||||
*/
|
||||
public class CommandLineArgument
|
||||
{
|
||||
List<CommandLineArgument> _arguments;
|
||||
|
||||
int _index;
|
||||
|
||||
string _argumentText;
|
||||
|
||||
public CommandLineArgument Next
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_index < _arguments.Count - 1)
|
||||
{
|
||||
return _arguments[_index + 1];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
public CommandLineArgument Previous
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_index > 0)
|
||||
{
|
||||
return _arguments[_index - 1];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
internal CommandLineArgument(List<CommandLineArgument> args, int index, string argument)
|
||||
{
|
||||
_arguments = args;
|
||||
_index = index;
|
||||
_argumentText = argument;
|
||||
}
|
||||
|
||||
public CommandLineArgument Take()
|
||||
{
|
||||
return Next;
|
||||
}
|
||||
|
||||
public IEnumerable<CommandLineArgument> Take(int count)
|
||||
{
|
||||
var list = new List<CommandLineArgument>();
|
||||
var parent = this;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
var next = parent.Next;
|
||||
if (next == null)
|
||||
break;
|
||||
|
||||
list.Add(next);
|
||||
|
||||
parent = next;
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
public static implicit operator string(CommandLineArgument argument)
|
||||
{
|
||||
return argument._argumentText;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return _argumentText;
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,39 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace N_m3u8DL_CLI
|
||||
{
|
||||
public class CommandLineArgumentParser
|
||||
{
|
||||
|
||||
List<CommandLineArgument> _arguments;
|
||||
public static CommandLineArgumentParser Parse(string[] args)
|
||||
{
|
||||
return new CommandLineArgumentParser(args);
|
||||
}
|
||||
|
||||
public CommandLineArgumentParser(string[] args)
|
||||
{
|
||||
_arguments = new List<CommandLineArgument>();
|
||||
|
||||
for (int i = 0; i < args.Length; i++)
|
||||
{
|
||||
_arguments.Add(new CommandLineArgument(_arguments, i, args[i]));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public CommandLineArgument Get(string argumentName)
|
||||
{
|
||||
return _arguments.FirstOrDefault(p => p == argumentName);
|
||||
}
|
||||
|
||||
public bool Has(string argumentName)
|
||||
{
|
||||
return _arguments.Count(p => p == argumentName) > 0;
|
||||
}
|
||||
}
|
||||
}
|
83
N_m3u8DL-CLI/DecodeCdeledu.cs
Normal file
83
N_m3u8DL-CLI/DecodeCdeledu.cs
Normal file
@@ -0,0 +1,83 @@
|
||||
using NiL.JS.BaseLibrary;
|
||||
using NiL.JS.Core;
|
||||
using NiL.JS.Extensions;
|
||||
using System;
|
||||
using Array = System.Array;
|
||||
|
||||
namespace N_m3u8DL_CLI
|
||||
{
|
||||
internal class DecodeCdeledu
|
||||
{
|
||||
private static string JS = @"
|
||||
var _keyStr = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
|
||||
|
||||
var removePaddingChars = function(input) {
|
||||
var lkey = _keyStr.indexOf(input.charAt(input.length - 1));
|
||||
if (lkey == 64) {
|
||||
return input.substring(0, input.length - 1);
|
||||
}
|
||||
return input;
|
||||
}
|
||||
|
||||
var base64Decode = function(input, arrayBuffer) {
|
||||
input = removePaddingChars(input);
|
||||
input = removePaddingChars(input);
|
||||
var bytes = parseInt((input.length / 4) * 3, 10);
|
||||
var uarray;
|
||||
var chr1, chr2, chr3;
|
||||
var enc1, enc2, enc3, enc4;
|
||||
var i = 0;
|
||||
var j = 0;
|
||||
if (arrayBuffer) {
|
||||
uarray = new Uint8Array(arrayBuffer);
|
||||
} else {
|
||||
uarray = new Uint8Array(bytes);
|
||||
}
|
||||
input = input.replace(/[^A-Za-z0-9\+\/\=]/g, '');
|
||||
for (i = 0; i < bytes; i += 3) {
|
||||
enc1 = _keyStr.indexOf(input.charAt(j++));
|
||||
enc2 = _keyStr.indexOf(input.charAt(j++));
|
||||
enc3 = _keyStr.indexOf(input.charAt(j++));
|
||||
enc4 = _keyStr.indexOf(input.charAt(j++));
|
||||
chr1 = (enc1 << 2) | (enc2 >> 4);
|
||||
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
|
||||
chr3 = ((enc3 & 3) << 6) | enc4;
|
||||
uarray[i] = chr1;
|
||||
if (enc3 != 64)
|
||||
uarray[i + 1] = chr2;
|
||||
if (enc4 != 64)
|
||||
uarray[i + 2] = chr3;
|
||||
}
|
||||
return uarray;
|
||||
}
|
||||
|
||||
var uint8ArrayToString = function(uDataArr) {
|
||||
var arrStr = '';
|
||||
for (var i = 0; i < uDataArr.length; i++) {
|
||||
arrStr += String.fromCharCode(uDataArr[i]);
|
||||
}
|
||||
return arrStr;
|
||||
}
|
||||
|
||||
var decodeKey = function(dataKeyString) {
|
||||
var decodeArr = base64Decode(dataKeyString);
|
||||
var decodeArrString = uint8ArrayToString(decodeArr);
|
||||
return decodeArrString;
|
||||
if (decodeArrString.indexOf('|&|') > 0) {
|
||||
return decodeArrString;
|
||||
}
|
||||
return '';
|
||||
}
|
||||
";
|
||||
//https://video.cdeledu.com/js/lib/cdel.hls.min-1.0.js?v=1.3
|
||||
public static string DecodeKey(string txt)
|
||||
{
|
||||
var context = new Context();
|
||||
context.Eval(JS);
|
||||
var concatFunction = context.GetVariable("decodeKey").As<Function>();
|
||||
string key = concatFunction.Call(new Arguments { txt }).ToString();
|
||||
string realKey = key.Split(new string[] { "|&|" }, StringSplitOptions.None)[1];
|
||||
return realKey;
|
||||
}
|
||||
}
|
||||
}
|
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);
|
||||
}
|
||||
}
|
||||
}
|
53
N_m3u8DL-CLI/DecodeHuke88Key.cs
Normal file
53
N_m3u8DL-CLI/DecodeHuke88Key.cs
Normal file
@@ -0,0 +1,53 @@
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace N_m3u8DL_CLI
|
||||
{
|
||||
//https://js.huke88.com/assets/revision/js/plugins/tcplayer/tcplayer.v4.1.min.js?v=930
|
||||
//https://js.huke88.com/assets/revision/js/plugins/tcplayer/libs/hls.min.0.13.2m.js?v=930
|
||||
class DecodeHuke88Key
|
||||
{
|
||||
private static string[] GetOverlayInfo(string url)
|
||||
{
|
||||
var enc = new Regex("eyJ\\w{100,}").Match(url).Value;
|
||||
var json = Encoding.UTF8.GetString(Convert.FromBase64String(enc));
|
||||
JObject jObject = JObject.Parse(json);
|
||||
var key = jObject["overlayKey"].ToString();
|
||||
var iv = jObject["overlayIv"].ToString();
|
||||
return new string[] { key, iv };
|
||||
}
|
||||
|
||||
public static string DecodeKey(string url, byte[] data)
|
||||
{
|
||||
var info = GetOverlayInfo(url);
|
||||
var overlayKey = info[0];
|
||||
var overlayIv = info[1];
|
||||
var l = new List<byte>();
|
||||
var c = new List<byte>();
|
||||
for (int h = 0; h < 16; h++)
|
||||
{
|
||||
var f = overlayKey.Substring(2 * h, 2);
|
||||
var g = overlayIv.Substring(2 * h, 2);
|
||||
l.Add(Convert.ToByte(f, 16));
|
||||
c.Add(Convert.ToByte(g, 16));
|
||||
}
|
||||
|
||||
var _lastCipherblock = c.ToArray();
|
||||
|
||||
var t = new byte[data.Length];
|
||||
var r = data;
|
||||
r = Decrypter.AES128Decrypt(data, l.ToArray(), Decrypter.HexStringToBytes("00000000000000000000000000000000"), CipherMode.CBC, PaddingMode.Zeros);
|
||||
|
||||
for (var o = 0; o < 16; o++)
|
||||
t[o] = (byte)(r[o] ^ _lastCipherblock[o]);
|
||||
|
||||
var key = Convert.ToBase64String(t);
|
||||
|
||||
return key;
|
||||
}
|
||||
}
|
||||
}
|
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;
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,16 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using CSChaCha20;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace N_m3u8DL_CLI
|
||||
{
|
||||
class Decrypter
|
||||
{
|
||||
public static byte[] AES128Decrypt(string filePath, byte[] keyByte, byte[] ivByte, CipherMode mode = CipherMode.CBC)
|
||||
public static byte[] AES128Decrypt(string filePath, byte[] keyByte, byte[] ivByte, CipherMode mode = CipherMode.CBC, PaddingMode padding = PaddingMode.PKCS7)
|
||||
{
|
||||
FileStream fs = new FileStream(filePath, FileMode.Open);
|
||||
//获取文件大小
|
||||
@@ -25,14 +23,14 @@ namespace N_m3u8DL_CLI
|
||||
dcpt.Key = keyByte;
|
||||
dcpt.IV = ivByte;
|
||||
dcpt.Mode = mode;
|
||||
dcpt.Padding = PaddingMode.PKCS7;
|
||||
dcpt.Padding = padding;
|
||||
|
||||
ICryptoTransform cTransform = dcpt.CreateDecryptor();
|
||||
Byte[] resultArray = cTransform.TransformFinalBlock(inBuff, 0, inBuff.Length);
|
||||
return resultArray;
|
||||
}
|
||||
|
||||
public static byte[] AES128Decrypt(byte[] encryptedBuff, byte[] keyByte, byte[] ivByte, CipherMode mode = CipherMode.CBC)
|
||||
public static byte[] AES128Decrypt(byte[] encryptedBuff, byte[] keyByte, byte[] ivByte, CipherMode mode = CipherMode.CBC, PaddingMode padding = PaddingMode.PKCS7)
|
||||
{
|
||||
byte[] inBuff = encryptedBuff;
|
||||
|
||||
@@ -42,13 +40,47 @@ namespace N_m3u8DL_CLI
|
||||
dcpt.Key = keyByte;
|
||||
dcpt.IV = ivByte;
|
||||
dcpt.Mode = mode;
|
||||
dcpt.Padding = PaddingMode.PKCS7;
|
||||
dcpt.Padding = padding;
|
||||
|
||||
ICryptoTransform cTransform = dcpt.CreateDecryptor();
|
||||
Byte[] resultArray = cTransform.TransformFinalBlock(inBuff, 0, inBuff.Length);
|
||||
return resultArray;
|
||||
}
|
||||
|
||||
public static byte[] CHACHA20Decrypt(byte[] encryptedBuff, byte[] keyBytes, byte[] nonceBytes)
|
||||
{
|
||||
if (keyBytes.Length != 32)
|
||||
throw new Exception("Key must be 32 bytes!");
|
||||
if (nonceBytes.Length != 12 && nonceBytes.Length != 8)
|
||||
throw new Exception("Key must be 12 or 8 bytes!");
|
||||
if (nonceBytes.Length == 8)
|
||||
nonceBytes = (new byte[4] { 0, 0, 0, 0 }).Concat(nonceBytes).ToArray();
|
||||
|
||||
var decStream = new MemoryStream();
|
||||
using (BinaryReader reader = new BinaryReader(new MemoryStream(encryptedBuff)))
|
||||
{
|
||||
using (BinaryWriter writer = new BinaryWriter(decStream))
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
var buffer = reader.ReadBytes(1024);
|
||||
byte[] dec = new byte[buffer.Length];
|
||||
if (buffer.Length > 0)
|
||||
{
|
||||
ChaCha20 forDecrypting = new ChaCha20(keyBytes, nonceBytes, 0);
|
||||
forDecrypting.DecryptBytes(dec, buffer);
|
||||
writer.Write(dec, 0, dec.Length);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return decStream.ToArray();
|
||||
}
|
||||
|
||||
public static byte[] HexStringToBytes(string hexStr)
|
||||
{
|
||||
if (string.IsNullOrEmpty(hexStr))
|
||||
@@ -56,7 +88,7 @@ namespace N_m3u8DL_CLI
|
||||
return new byte[0];
|
||||
}
|
||||
|
||||
if (hexStr.StartsWith("0x") || hexStr.StartsWith("0X"))
|
||||
if (hexStr.StartsWith("0x") || hexStr.StartsWith("0X"))
|
||||
{
|
||||
hexStr = hexStr.Remove(0, 2);
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -47,6 +47,10 @@ namespace N_m3u8DL_CLI
|
||||
public long ExpectByte { get => expectByte; set => expectByte = value; }
|
||||
public long StartByte { get => startByte; set => startByte = value; }
|
||||
public double SegDur { get => segDur; set => segDur = value; }
|
||||
|
||||
public static bool EnableChaCha20 { get; set; } = false;
|
||||
public static string ChaCha20KeyBase64 { get; set; }
|
||||
public static string ChaCha20NonceBase64 { get; set; }
|
||||
|
||||
//重写WebClinet
|
||||
//private class WebClient : System.Net.WebClient
|
||||
@@ -179,9 +183,18 @@ namespace N_m3u8DL_CLI
|
||||
if (File.Exists(savePath) && Global.ShouldStop == false)
|
||||
{
|
||||
FileInfo fi = new FileInfo(savePath);
|
||||
if (Method == "NONE" || method.Contains("NOTSUPPORTED"))
|
||||
if (File.Exists(fi.FullName) && EnableChaCha20)
|
||||
{
|
||||
fi.MoveTo(Path.GetDirectoryName(savePath) + "\\" + Path.GetFileNameWithoutExtension(savePath) + ".ts");
|
||||
byte[] decryptBuff = Decrypter.CHACHA20Decrypt(File.ReadAllBytes(fi.FullName), Convert.FromBase64String(ChaCha20KeyBase64), Convert.FromBase64String(ChaCha20NonceBase64));
|
||||
FileStream fs = new FileStream(Path.GetDirectoryName(SavePath) + "\\" + Path.GetFileNameWithoutExtension(SavePath) + ".ts", FileMode.Create);
|
||||
fs.Write(decryptBuff, 0, decryptBuff.Length);
|
||||
fs.Close();
|
||||
DownloadManager.DownloadedSize += fi.Length;
|
||||
fi.Delete();
|
||||
}
|
||||
else if (Method == "NONE" || Method.Contains("NOTSUPPORTED"))
|
||||
{
|
||||
fi.MoveTo(Path.GetDirectoryName(SavePath) + "\\" + Path.GetFileNameWithoutExtension(SavePath) + ".ts");
|
||||
DownloadManager.DownloadedSize += fi.Length;
|
||||
//Console.WriteLine(Path.GetFileNameWithoutExtension(savePath) + " Completed.");
|
||||
}
|
||||
@@ -249,4 +262,4 @@ namespace N_m3u8DL_CLI
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -10,19 +10,20 @@ 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()}"))
|
||||
{
|
||||
@@ -50,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 + "\" ";
|
||||
@@ -83,7 +84,7 @@ namespace N_m3u8DL_CLI
|
||||
|
||||
}
|
||||
|
||||
Run("ffmpeg", command, Path.GetDirectoryName(files[0]));
|
||||
Run(FFMPEG_PATH, command, Path.GetDirectoryName(files[0]));
|
||||
LOGGER.WriteLine(strings.ffmpegDone);
|
||||
//Console.WriteLine(command);
|
||||
}
|
||||
@@ -92,7 +93,7 @@ namespace N_m3u8DL_CLI
|
||||
{
|
||||
if (Global.VIDEO_TYPE == "H264")
|
||||
{
|
||||
Run("ffmpeg",
|
||||
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));
|
||||
@@ -104,7 +105,7 @@ namespace N_m3u8DL_CLI
|
||||
}
|
||||
else if (Global.VIDEO_TYPE == "H265")
|
||||
{
|
||||
Run("ffmpeg",
|
||||
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));
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -62,6 +62,7 @@ namespace N_m3u8DL_CLI
|
||||
targetduration = initJson["m3u8Info"]["targetDuration"].Value<double>();
|
||||
TotalDuration = initJson["m3u8Info"]["totalDuration"].Value<double>();
|
||||
timer.Interval = (TotalDuration - targetduration) * 1000;//设置定时器运行间隔
|
||||
if (timer.Interval <= 1000) timer.Interval = 10000;
|
||||
JArray lastSegments = JArray.Parse(initJson["m3u8Info"]["segments"][0].ToString().Trim()); //上次的分段,用于比对新分段
|
||||
ArrayList tempList = new ArrayList(); //所有待下载的列表
|
||||
tempList.Clear();
|
||||
@@ -127,6 +128,7 @@ namespace N_m3u8DL_CLI
|
||||
sd.Iv = info["iv"].Value<string>();
|
||||
}
|
||||
sd.TimeOut = (int)timer.Interval - 1000;//超时时间不超过下次执行时间
|
||||
if (sd.TimeOut <= 0) sd.TimeOut = (int)timer.Interval;
|
||||
sd.SegIndex = index;
|
||||
sd.Headers = Headers;
|
||||
sd.SegDur = info["duration"].Value<double>();
|
||||
|
116
N_m3u8DL-CLI/IqJsonParser.cs
Normal file
116
N_m3u8DL-CLI/IqJsonParser.cs
Normal file
@@ -0,0 +1,116 @@
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace N_m3u8DL_CLI
|
||||
{
|
||||
class IqJsonParser
|
||||
{
|
||||
public static string Parse(string downDir, string json)
|
||||
{
|
||||
JObject jObject = JObject.Parse(json);
|
||||
var aClips = jObject["payload"]["wm_a"]["audio_track1"]["files"].Value<JArray>();
|
||||
var vClips = jObject["payload"]["wm_a"]["video_track1"]["files"].Value<JArray>();
|
||||
|
||||
var codecsList = new List<string>();
|
||||
|
||||
var audioPath = "";
|
||||
var videoPath = "";
|
||||
var audioInitPath = "";
|
||||
var videoInitPath = "";
|
||||
|
||||
if (aClips.Count > 0)
|
||||
{
|
||||
var init = jObject["payload"]["wm_a"]["audio_track1"]["codec_init"].Value<string>();
|
||||
byte[] bytes = Convert.FromBase64String(init);
|
||||
//输出init文件
|
||||
audioInitPath = Path.Combine(downDir, "iqAudioInit.mp4");
|
||||
File.WriteAllBytes(audioInitPath, bytes);
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.AppendLine("#EXTM3U");
|
||||
sb.AppendLine("#EXT-X-VERSION:3");
|
||||
sb.AppendLine("#EXT-X-PLAYLIST-TYPE:VOD");
|
||||
sb.AppendLine("#CREATED-BY:N_m3u8DL-CLI");
|
||||
sb.AppendLine($"#EXT-CODEC:{jObject["payload"]["wm_a"]["audio_track1"]["codec"].Value<string>()}");
|
||||
sb.AppendLine($"#EXT-KID:{jObject["payload"]["wm_a"]["audio_track1"]["key_id"].Value<string>()}");
|
||||
sb.AppendLine($"#EXT-X-MAP:URI=\"{new Uri(Path.Combine(downDir + "(Audio)", "iqAudioInit.mp4")).ToString()}\"");
|
||||
sb.AppendLine("#EXT-X-KEY:METHOD=PLZ-KEEP-RAW,URI=\"None\"");
|
||||
foreach (var a in aClips)
|
||||
{
|
||||
sb.AppendLine($"#EXTINF:{a["duration_second"].ToString()}");
|
||||
sb.AppendLine(a["file_name"].Value<string>());
|
||||
}
|
||||
sb.AppendLine("#EXT-X-ENDLIST");
|
||||
//输出m3u8文件
|
||||
var _path = Path.Combine(downDir, "iqAudio.m3u8");
|
||||
File.WriteAllText(_path, sb.ToString());
|
||||
audioPath = new Uri(_path).ToString();
|
||||
codecsList.Add(jObject["payload"]["wm_a"]["audio_track1"]["codec"].Value<string>());
|
||||
}
|
||||
|
||||
if (vClips.Count > 0)
|
||||
{
|
||||
var init = jObject["payload"]["wm_a"]["video_track1"]["codec_init"].Value<string>();
|
||||
byte[] bytes = Convert.FromBase64String(init);
|
||||
//输出init文件
|
||||
videoInitPath = Path.Combine(downDir, "iqVideoInit.mp4");
|
||||
File.WriteAllBytes(videoInitPath, bytes);
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.AppendLine("#EXTM3U");
|
||||
sb.AppendLine("#EXT-X-VERSION:3");
|
||||
sb.AppendLine("#EXT-X-PLAYLIST-TYPE:VOD");
|
||||
sb.AppendLine("#CREATED-BY:N_m3u8DL-CLI");
|
||||
sb.AppendLine($"#EXT-CODEC:{jObject["payload"]["wm_a"]["video_track1"]["codec"].Value<string>()}");
|
||||
sb.AppendLine($"#EXT-KID:{jObject["payload"]["wm_a"]["video_track1"]["key_id"].Value<string>()}");
|
||||
sb.AppendLine($"#EXT-X-MAP:URI=\"{new Uri(videoInitPath).ToString()}\"");
|
||||
sb.AppendLine("#EXT-X-KEY:METHOD=PLZ-KEEP-RAW,URI=\"None\"");
|
||||
foreach (var a in vClips)
|
||||
{
|
||||
var start = a["seekable"]["pos_start"].Value<long>();
|
||||
var size = a["size"].Value<long>();
|
||||
sb.AppendLine($"#EXTINF:{a["duration_second"].ToString()}");
|
||||
sb.AppendLine($"#EXT-X-BYTERANGE:{size}@{start}");
|
||||
sb.AppendLine(a["file_name"].Value<string>());
|
||||
}
|
||||
sb.AppendLine("#EXT-X-ENDLIST");
|
||||
//输出m3u8文件
|
||||
var _path = Path.Combine(downDir, "iqVideo.m3u8");
|
||||
File.WriteAllText(_path, sb.ToString());
|
||||
videoPath = new Uri(_path).ToString();
|
||||
codecsList.Add(jObject["payload"]["wm_a"]["video_track1"]["codec"].Value<string>());
|
||||
}
|
||||
|
||||
var content = "";
|
||||
if ((videoPath == "" && audioPath != "") || Global.VIDEO_TYPE == "IGNORE")
|
||||
{
|
||||
return audioPath;
|
||||
}
|
||||
else if (audioPath == "" && videoPath != "")
|
||||
{
|
||||
return videoPath;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!Directory.Exists(downDir + "(Audio)"))
|
||||
Directory.CreateDirectory(downDir + "(Audio)");
|
||||
var _path = Path.Combine(downDir + "(Audio)", "iqAudio.m3u8");
|
||||
var _pathInit = Path.Combine(downDir + "(Audio)", "iqAudioInit.mp4");
|
||||
File.Copy(new Uri(audioPath).LocalPath, _path, true);
|
||||
File.Copy(new Uri(audioInitPath).LocalPath, _pathInit, true);
|
||||
audioPath = new Uri(_path).ToString();
|
||||
content = $"#EXTM3U\r\n" +
|
||||
$"#EXT-X-MEDIA:TYPE=AUDIO,URI=\"{audioPath}\",GROUP-ID=\"default-audio-group\",NAME=\"stream_0\",AUTOSELECT=YES,CHANNELS=\"0\"\r\n" +
|
||||
$"#EXT-X-STREAM-INF:BANDWIDTH=99999,CODECS=\"{string.Join(",", codecsList)}\",RESOLUTION=0x0,AUDIO=\"default-audio-group\"\r\n" +
|
||||
$"{videoPath}";
|
||||
}
|
||||
|
||||
var _masterPath = Path.Combine(downDir, "master.m3u8");
|
||||
File.WriteAllText(_masterPath, content);
|
||||
return new Uri(_masterPath).ToString();
|
||||
}
|
||||
}
|
||||
}
|
@@ -11,8 +11,6 @@ namespace N_m3u8DL_CLI
|
||||
{
|
||||
class LOGGER
|
||||
{
|
||||
public static int CursorIndex = 5;
|
||||
public static int FFmpegCorsorIndex = 5;
|
||||
public const int Default = 1;
|
||||
public const int Error = 2;
|
||||
public const int Warning = 3;
|
||||
@@ -36,8 +34,13 @@ namespace N_m3u8DL_CLI
|
||||
{
|
||||
if (!Directory.Exists(Path.GetDirectoryName(LOGFILE)))//若文件夹不存在则新建文件夹
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(LOGFILE)); //新建文件夹
|
||||
if (File.Exists(LOGFILE))//若文件存在则删除
|
||||
File.Delete(LOGFILE);
|
||||
//若文件存在则加序号
|
||||
int index = 1;
|
||||
var fileName = Path.GetFileNameWithoutExtension(LOGFILE);
|
||||
while (File.Exists(LOGFILE))
|
||||
{
|
||||
LOGFILE = Path.Combine(Path.GetDirectoryName(LOGFILE), $"{fileName}-{index++}.log");
|
||||
}
|
||||
string file = LOGFILE;
|
||||
string now = DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss");
|
||||
string init = "LOG " + DateTime.Now.ToString("yyyy/MM/dd") + "\r\n"
|
||||
@@ -57,40 +60,37 @@ namespace N_m3u8DL_CLI
|
||||
//读写锁机制,当资源被占用,其他线程等待
|
||||
static ReaderWriterLockSlim LogWriteLock = new ReaderWriterLockSlim();
|
||||
|
||||
public static void PrintLine(string text, int printLevel = 1, int cursorIndex = 0)
|
||||
public static void PrintLine(string text, int printLevel = 1)
|
||||
{
|
||||
int windowWith = 63;
|
||||
try
|
||||
{
|
||||
if (CursorIndex > 1000)
|
||||
{
|
||||
Console.Clear();
|
||||
CursorIndex = 0;
|
||||
}
|
||||
if (cursorIndex == 0)
|
||||
Console.SetCursorPosition(0, CursorIndex++);
|
||||
else
|
||||
Console.SetCursorPosition(0, cursorIndex);
|
||||
windowWith = Console.WindowWidth;
|
||||
}
|
||||
catch (Exception)
|
||||
catch (Exception e)
|
||||
{
|
||||
;
|
||||
// empty
|
||||
}
|
||||
switch (printLevel)
|
||||
{
|
||||
case 0:
|
||||
Console.Write("\r" + new string(' ', windowWith - 1) + "\r");
|
||||
Console.WriteLine(" ".PadRight(12) + " " + text);
|
||||
break;
|
||||
case 1:
|
||||
Console.Write("\r" + new string(' ', windowWith - 1) + "\r");
|
||||
Console.Write(DateTime.Now.ToString("HH:mm:ss.fff") + " ");
|
||||
Console.WriteLine(text);
|
||||
break;
|
||||
case 2:
|
||||
Console.Write("\r" + new string(' ', windowWith - 1) + "\r");
|
||||
Console.Write(DateTime.Now.ToString("HH:mm:ss.fff") + " ");
|
||||
Console.ForegroundColor = ConsoleColor.Red;
|
||||
Console.WriteLine(text);
|
||||
Console.ResetColor();
|
||||
break;
|
||||
case 3:
|
||||
Console.Write("\r" + new string(' ', windowWith - 1) + "\r");
|
||||
Console.Write(DateTime.Now.ToString("HH:mm:ss.fff") + " ");
|
||||
Console.ForegroundColor = ConsoleColor.DarkYellow;
|
||||
Console.WriteLine(text);
|
||||
@@ -118,7 +118,7 @@ namespace N_m3u8DL_CLI
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -143,7 +143,7 @@ namespace N_m3u8DL_CLI
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -156,7 +156,7 @@ namespace N_m3u8DL_CLI
|
||||
{
|
||||
Console.ForegroundColor = ConsoleColor.Red;
|
||||
Console.WriteLine(DateTime.Now.ToString("o") + " " + text);
|
||||
while (Console.ForegroundColor == ConsoleColor.Red)
|
||||
while (Console.ForegroundColor == ConsoleColor.Red)
|
||||
Console.ResetColor();
|
||||
}
|
||||
}
|
||||
|
867
N_m3u8DL-CLI/MPDParser.cs
Normal file
867
N_m3u8DL-CLI/MPDParser.cs
Normal file
File diff suppressed because it is too large
Load Diff
110
N_m3u8DL-CLI/MyOptions.cs
Normal file
110
N_m3u8DL-CLI/MyOptions.cs
Normal file
@@ -0,0 +1,110 @@
|
||||
using CommandLine;
|
||||
using CommandLine.Text;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace N_m3u8DL_CLI
|
||||
{
|
||||
internal class MyOptions
|
||||
{
|
||||
[Value(0, Hidden = true, MetaName = "Input Source", HelpText = "Help_input", ResourceType = typeof(strings))]
|
||||
public string Input { get; set; }
|
||||
|
||||
[Option("workDir", HelpText = "Help_workDir", ResourceType = typeof(strings))]
|
||||
public string WorkDir { get; set; }
|
||||
|
||||
[Option("saveName", HelpText = "Help_saveName", ResourceType = typeof(strings))]
|
||||
public string SaveName { get; set; } = "";
|
||||
|
||||
[Option("baseUrl", HelpText = "Help_baseUrl", ResourceType = typeof(strings))]
|
||||
public string BaseUrl { get; set; }
|
||||
|
||||
[Option("headers", HelpText = "Help_headers", ResourceType = typeof(strings))]
|
||||
public string Headers { get; set; } = "";
|
||||
|
||||
[Option("maxThreads", Default = 32U, HelpText = "Help_maxThreads", ResourceType = typeof(strings))]
|
||||
public uint MaxThreads { get; set; }
|
||||
|
||||
[Option("minThreads", Default = 16U, HelpText = "Help_minThreads", ResourceType = typeof(strings))]
|
||||
public uint MinThreads { get; set; }
|
||||
|
||||
[Option("retryCount", Default = 15U, HelpText = "Help_retryCount", ResourceType = typeof(strings))]
|
||||
public uint RetryCount { get; set; }
|
||||
|
||||
[Option("timeOut", Default = 10U, HelpText = "Help_timeOut", ResourceType = typeof(strings))]
|
||||
public uint TimeOut { get; set; }
|
||||
|
||||
[Option("muxSetJson", HelpText = "Help_muxSetJson", ResourceType = typeof(strings))]
|
||||
public string MuxSetJson { get; set; }
|
||||
|
||||
[Option("useKeyFile", HelpText = "Help_useKeyFile", ResourceType = typeof(strings))]
|
||||
public string UseKeyFile { get; set; }
|
||||
|
||||
[Option("useKeyBase64", HelpText = "Help_useKeyBase64", ResourceType = typeof(strings))]
|
||||
public string UseKeyBase64 { get; set; }
|
||||
|
||||
[Option("useKeyIV", HelpText = "Help_useKeyIV", ResourceType = typeof(strings))]
|
||||
public string UseKeyIV { get; set; }
|
||||
|
||||
[Option("downloadRange", HelpText = "Help_downloadRange", ResourceType = typeof(strings))]
|
||||
public string DownloadRange { get; set; }
|
||||
|
||||
[Option("liveRecDur", HelpText = "Help_liveRecDur", ResourceType = typeof(strings))]
|
||||
public string LiveRecDur { get; set; }
|
||||
|
||||
[Option("stopSpeed", HelpText = "Help_stopSpeed", ResourceType = typeof(strings))]
|
||||
public long StopSpeed { get; set; } = 0L;
|
||||
|
||||
[Option("maxSpeed", HelpText = "Help_maxSpeed", ResourceType = typeof(strings))]
|
||||
public long MaxSpeed { get; set; } = 0L;
|
||||
|
||||
[Option("proxyAddress", HelpText = "Help_proxyAddress", ResourceType = typeof(strings))]
|
||||
public string ProxyAddress { get; set; }
|
||||
|
||||
[Option("enableDelAfterDone", HelpText = "Help_enableDelAfterDone", ResourceType = typeof(strings))]
|
||||
public bool EnableDelAfterDone { get; set; }
|
||||
|
||||
[Option("enableMuxFastStart", HelpText = "Help_enableMuxFastStart", ResourceType = typeof(strings))]
|
||||
public bool EnableMuxFastStart { get; set; }
|
||||
|
||||
[Option("enableBinaryMerge", HelpText = "Help_enableBinaryMerge", ResourceType = typeof(strings))]
|
||||
public bool EnableBinaryMerge { get; set; }
|
||||
|
||||
[Option("enableParseOnly", HelpText = "Help_enableParseOnly", ResourceType = typeof(strings))]
|
||||
public bool EnableParseOnly { get; set; }
|
||||
|
||||
[Option("enableAudioOnly", HelpText = "Help_enableAudioOnly", ResourceType = typeof(strings))]
|
||||
public bool EnableAudioOnly { get; set; }
|
||||
|
||||
[Option("disableDateInfo", HelpText = "Help_disableDateInfo", ResourceType = typeof(strings))]
|
||||
public bool DisableDateInfo { get; set; }
|
||||
|
||||
[Option("disableIntegrityCheck", HelpText = "Help_disableIntegrityCheck", ResourceType = typeof(strings))]
|
||||
public bool DisableIntegrityCheck { get; set; }
|
||||
|
||||
[Option("noMerge", HelpText = "Help_noMerge", ResourceType = typeof(strings))]
|
||||
public bool NoMerge { get; set; }
|
||||
|
||||
[Option("noProxy", HelpText = "Help_noProxy", ResourceType = typeof(strings))]
|
||||
public bool NoProxy { get; set; }
|
||||
|
||||
[Option("registerUrlProtocol", HelpText = "Help_registerUrlProtocol", ResourceType = typeof(strings))]
|
||||
public bool RegisterUrlProtocol { get; set; }
|
||||
|
||||
[Option("unregisterUrlProtocol", HelpText = "Help_unregisterUrlProtocol", ResourceType = typeof(strings))]
|
||||
public bool UnregisterUrlProtocol { get; set; }
|
||||
|
||||
[Option("enableChaCha20", HelpText = "enableChaCha20")]
|
||||
public bool EnableChaCha20 { get; set; }
|
||||
|
||||
[Option("chaCha20KeyBase64", HelpText = "ChaCha20KeyBase64")]
|
||||
public string ChaCha20KeyBase64 { get; set; }
|
||||
|
||||
[Option("chaCha20NonceBase64", HelpText = "ChaCha20NonceBase64")]
|
||||
public string ChaCha20NonceBase64 { get; set; }
|
||||
|
||||
}
|
||||
}
|
@@ -1,5 +1,7 @@
|
||||
<?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="..\packages\Resource.Embedder.2.1.1\build\Resource.Embedder.props" Condition="Exists('..\packages\Resource.Embedder.2.1.1\build\Resource.Embedder.props')" />
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
@@ -12,6 +14,8 @@
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
<TargetFrameworkProfile />
|
||||
<NuGetPackageImportStamp>
|
||||
</NuGetPackageImportStamp>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
@@ -38,42 +42,91 @@
|
||||
<ApplicationIcon>logo_3Iv_icon.ico</ApplicationIcon>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="BrotliSharpLib, Version=0.3.2.0, Culture=neutral, PublicKeyToken=3f4e2a1cd615fcb7, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\BrotliSharpLib.0.3.3\lib\net451\BrotliSharpLib.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="CommandLine, Version=2.8.0.0, Culture=neutral, PublicKeyToken=5a870481e358d379, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\CommandLineParser.2.8.0\lib\net45\CommandLine.dll</HintPath>
|
||||
</Reference>
|
||||
<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.Build.Framework" />
|
||||
<Reference Include="Microsoft.Build.Utilities.v4.0" />
|
||||
<Reference Include="Microsoft.JScript" />
|
||||
<Reference Include="Microsoft.Win32.TaskScheduler, Version=2.8.7.0, Culture=neutral, PublicKeyToken=c416bc1b32d97233, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\TaskScheduler.2.8.7\lib\net452\Microsoft.Win32.TaskScheduler.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="MihaZupan.HttpToSocks5Proxy, Version=1.4.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\HttpToSocks5Proxy.1.4.0\lib\net45\MihaZupan.HttpToSocks5Proxy.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="netstandard, Version=2.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51" />
|
||||
<Reference Include="Newtonsoft.Json">
|
||||
<HintPath>..\packages\Newtonsoft.Json.dll</HintPath>
|
||||
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Newtonsoft.Json.13.0.1\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.dll</HintPath>
|
||||
<HintPath>..\packages\NiL.JS.2.5.1428\lib\net45\NiL.JS.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="PresentationFramework" />
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Collections" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.IO" />
|
||||
<Reference Include="System.IO.Compression" />
|
||||
<Reference Include="System.Runtime.CompilerServices.Unsafe, Version=4.0.4.1, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Runtime.CompilerServices.Unsafe.4.5.2\lib\netstandard1.0\System.Runtime.CompilerServices.Unsafe.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Web" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="UACHelper, Version=1.3.0.4, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\UACHelper.1.3.0.5\lib\net40\UACHelper.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="CommandLineArgument.cs" />
|
||||
<Compile Include="CommandLineArgumentParser.cs" />
|
||||
<Compile Include="CSChaCha20.cs" />
|
||||
<Compile Include="Decode51CtoKey.cs" />
|
||||
<Compile Include="DecodeCdeledu.cs" />
|
||||
<Compile Include="DecodeDdyun.cs" />
|
||||
<Compile Include="DecodeHuke88Key.cs" />
|
||||
<Compile Include="DecodeImooc.cs" />
|
||||
<Compile Include="Decrypter.cs" />
|
||||
<Compile Include="DecodeNfmovies.cs" />
|
||||
<Compile Include="FFmpeg.cs" />
|
||||
<Compile Include="Global.cs" />
|
||||
<Compile Include="HLSLiveDownloader.cs" />
|
||||
<Compile Include="HLSTags.cs" />
|
||||
<Compile Include="IqJsonParser.cs" />
|
||||
<Compile Include="LOGGER.cs" />
|
||||
<Compile Include="DownloadManager.cs" />
|
||||
<Compile Include="MPDParser.cs" />
|
||||
<Compile Include="MyOptions.cs" />
|
||||
<Compile Include="Parser.cs" />
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="ProgressReporter.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>
|
||||
@@ -82,9 +135,6 @@
|
||||
</None>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="bin\Debug\Newtonsoft.Json.dll" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<COMReference Include="Scripting">
|
||||
<Guid>{420B2830-E718-11CF-893D-00A0C9054228}</Guid>
|
||||
@@ -100,16 +150,30 @@
|
||||
<Content Include="logo_3Iv_icon.ico" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Properties\Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
<EmbeddedResource Include="strings.en-US.resx">
|
||||
<Generator>PublicResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>strings.en-US.Designer.cs</LastGenOutput>
|
||||
<SubType>Designer</SubType>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="strings.en-US.resx" />
|
||||
<EmbeddedResource Include="strings.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<Generator>PublicResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>strings.Designer.cs</LastGenOutput>
|
||||
<SubType>Designer</SubType>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="strings.zh-TW.resx">
|
||||
<Generator>PublicResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>strings.zh-TW.Designer.cs</LastGenOutput>
|
||||
<SubType>Designer</SubType>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="strings.zh-TW.resx" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>这台计算机上缺少此项目引用的 NuGet 程序包。使用“NuGet 程序包还原”可下载这些程序包。有关更多信息,请参见 http://go.microsoft.com/fwlink/?LinkID=322105。缺少的文件是 {0}。</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\packages\Resource.Embedder.2.1.1\build\Resource.Embedder.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Resource.Embedder.2.1.1\build\Resource.Embedder.props'))" />
|
||||
<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>
|
||||
<Import Project="..\packages\Fody.6.0.0\build\Fody.targets" Condition="Exists('..\packages\Fody.6.0.0\build\Fody.targets')" />
|
||||
</Project>
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
39
N_m3u8DL-CLI/ProgressReporter.cs
Normal file
39
N_m3u8DL-CLI/ProgressReporter.cs
Normal file
@@ -0,0 +1,39 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace N_m3u8DL_CLI
|
||||
{
|
||||
class ProgressReporter
|
||||
{
|
||||
private static string speed = "";
|
||||
private static string progress = "";
|
||||
|
||||
static object lockThis = new object();
|
||||
public static void Report(string progress, string speed)
|
||||
{
|
||||
lock (lockThis)
|
||||
{
|
||||
int windowWith = 63;
|
||||
try
|
||||
{
|
||||
windowWith = Console.WindowWidth;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
// empty
|
||||
}
|
||||
if (!string.IsNullOrEmpty(progress)) ProgressReporter.progress = progress;
|
||||
if (!string.IsNullOrEmpty(speed)) ProgressReporter.speed = speed;
|
||||
string now = DateTime.Now.ToString("HH:mm:ss.000");
|
||||
var sub = windowWith - 4 - ProgressReporter.progress.Length - ProgressReporter.speed.Length - now.Length;
|
||||
if (sub <= 0) sub = 0;
|
||||
string print = now + " " + ProgressReporter.progress + " " + ProgressReporter.speed + new string(' ', sub);
|
||||
Console.Write("\r" + print + "\r");
|
||||
//Console.Write(print);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -10,7 +10,7 @@ using System.Runtime.InteropServices;
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("nilaoda")]
|
||||
[assembly: AssemblyProduct("N_m3u8DL-CLI")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2020")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2022")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
|
||||
// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号
|
||||
// 方法是按如下所示使用“*”: :
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("2.7.0.0")]
|
||||
[assembly: AssemblyVersion("3.0.2.0")]
|
||||
[assembly: AssemblyFileVersion("3.0.2.0")]
|
||||
|
@@ -59,10 +59,12 @@ namespace N_m3u8DL_CLI
|
||||
//Console.Title = Now + " / " + Total;
|
||||
string downloadedSize = Global.FormatFileSize(DownloadManager.DownloadedSize);
|
||||
string estimatedSize = Global.FormatFileSize(DownloadManager.DownloadedSize * total / now);
|
||||
int padding = downloadedSize.Length > estimatedSize.Length ? downloadedSize.Length : estimatedSize.Length;
|
||||
DownloadManager.ToDoSize = (DownloadManager.DownloadedSize * total / now) - DownloadManager.DownloadedSize;
|
||||
string percent = (Convert.ToDouble(now) / Convert.ToDouble(total) * 100).ToString("0.00") + "%";
|
||||
Console.SetCursorPosition(0, 2);
|
||||
Console.Write(("Progress: " + Now + " of " + Total
|
||||
+ $" ({percent}/{downloadedSize}/{estimatedSize}/{Global.FormatTime(Convert.ToInt32(TotalDuration))})").PadRight(62));
|
||||
var print = "Progress: " + Now + "/" + Total
|
||||
+ $" ({percent}) -- {downloadedSize.PadLeft(padding)}/{estimatedSize.PadRight(padding)}";
|
||||
ProgressReporter.Report(print, "");
|
||||
}
|
||||
|
||||
private void OnRenamed(object source, RenamedEventArgs e)
|
||||
@@ -77,10 +79,12 @@ namespace N_m3u8DL_CLI
|
||||
//Console.Title = Now + " / " + Total;
|
||||
string downloadedSize = Global.FormatFileSize(DownloadManager.DownloadedSize);
|
||||
string estimatedSize = Global.FormatFileSize(DownloadManager.DownloadedSize * total / now);
|
||||
int padding = downloadedSize.Length > estimatedSize.Length ? downloadedSize.Length : estimatedSize.Length;
|
||||
DownloadManager.ToDoSize = (DownloadManager.DownloadedSize * total / now) - DownloadManager.DownloadedSize;
|
||||
string percent = (Convert.ToDouble(now) / Convert.ToDouble(total) * 100).ToString("0.00") + "%";
|
||||
Console.SetCursorPosition(0, 2);
|
||||
Console.Write(("Progress: " + Now + " of " + Total
|
||||
+ $" ({percent}/{downloadedSize}/{estimatedSize}/{Global.FormatTime(Convert.ToInt32(TotalDuration))})").PadRight(62));
|
||||
var print = "Progress: " + Now + "/" + Total
|
||||
+ $" ({percent}) -- {downloadedSize.PadLeft(padding)}/{estimatedSize.PadRight(padding)}";
|
||||
ProgressReporter.Report(print, "");
|
||||
}
|
||||
|
||||
private void OnDeleted(object source, FileSystemEventArgs e)
|
||||
@@ -95,10 +99,12 @@ namespace N_m3u8DL_CLI
|
||||
//Console.Title = Now + " / " + Total;
|
||||
string downloadedSize = Global.FormatFileSize(DownloadManager.DownloadedSize);
|
||||
string estimatedSize = Global.FormatFileSize(DownloadManager.DownloadedSize * total / now);
|
||||
int padding = downloadedSize.Length > estimatedSize.Length ? downloadedSize.Length : estimatedSize.Length;
|
||||
DownloadManager.ToDoSize = (DownloadManager.DownloadedSize * total / now) - DownloadManager.DownloadedSize;
|
||||
string percent = (Convert.ToDouble(now) / Convert.ToDouble(total) * 100).ToString("0.00") + "%";
|
||||
Console.SetCursorPosition(0, 2);
|
||||
Console.Write(("Progress: " + Now + " of " + Total
|
||||
+ $" ({percent}/{downloadedSize}/{estimatedSize}/{Global.FormatTime(Convert.ToInt32(TotalDuration))})").PadRight(62));
|
||||
var print = "Progress: " + Now + "/" + Total
|
||||
+ $" ({percent}) -- {downloadedSize.PadLeft(padding)}/{estimatedSize.PadRight(padding)}";
|
||||
ProgressReporter.Report(print, "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
362
N_m3u8DL-CLI/changelog.txt
Normal file
362
N_m3u8DL-CLI/changelog.txt
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="BrotliSharpLib" version="0.3.3" targetFramework="net46" />
|
||||
<package id="CommandLineParser" version="2.8.0" targetFramework="net46" />
|
||||
<package id="Costura.Fody" version="4.1.0" targetFramework="net46" />
|
||||
<package id="Fody" version="6.0.0" targetFramework="net46" developmentDependency="true" />
|
||||
<package id="HttpToSocks5Proxy" version="1.4.0" targetFramework="net46" />
|
||||
<package id="Newtonsoft.Json" version="13.0.1" targetFramework="net46" />
|
||||
<package id="NiL.JS" version="2.5.1428" targetFramework="net46" />
|
||||
<package id="Resource.Embedder" version="2.1.1" targetFramework="net46" />
|
||||
<package id="System.Runtime.CompilerServices.Unsafe" version="4.5.2" targetFramework="net46" />
|
||||
<package id="TaskScheduler" version="2.8.7" targetFramework="net46" />
|
||||
<package id="UACHelper" version="1.3.0.5" targetFramework="net46" />
|
||||
</packages>
|
1378
N_m3u8DL-CLI/strings.Designer.cs
generated
1378
N_m3u8DL-CLI/strings.Designer.cs
generated
File diff suppressed because it is too large
Load Diff
@@ -183,34 +183,6 @@
|
||||
<data name="hasExternalSubtitleTrack" xml:space="preserve">
|
||||
<value>Has External Subtitle Track</value>
|
||||
</data>
|
||||
<data name="helpInfo" xml:space="preserve">
|
||||
<value>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</value>
|
||||
</data>
|
||||
<data name="invalidM3u8" xml:space="preserve">
|
||||
<value>Invalid M3u8 (NOT Contain #EXTM3U)</value>
|
||||
</data>
|
||||
@@ -298,4 +270,109 @@
|
||||
<data name="wrtingMeta" xml:space="preserve">
|
||||
<value>Writing Json: [meta.json]</value>
|
||||
</data>
|
||||
<data name="startParsingMpd" xml:space="preserve">
|
||||
<value>Start Parsing MPD Content...</value>
|
||||
</data>
|
||||
<data name="checkingLast" xml:space="preserve">
|
||||
<value>Checking Whether The Last Fragment Is Valid...</value>
|
||||
</data>
|
||||
<data name="Help_workDir" xml:space="preserve">
|
||||
<value>Set work dir (Video will be here)</value>
|
||||
</data>
|
||||
<data name="Help_saveName" xml:space="preserve">
|
||||
<value>Set save name(Exclude extention)</value>
|
||||
</data>
|
||||
<data name="Help_input" xml:space="preserve">
|
||||
<value>URL|File|JSON</value>
|
||||
</data>
|
||||
<data name="Help_baseUrl" xml:space="preserve">
|
||||
<value>Set Baseurl</value>
|
||||
</data>
|
||||
<data name="Help_headers" xml:space="preserve">
|
||||
<value>Set HTTP headers,format: key:value use | split all key&value</value>
|
||||
</data>
|
||||
<data name="Help_maxThreads" xml:space="preserve">
|
||||
<value>Set max thread</value>
|
||||
</data>
|
||||
<data name="Help_minThreads" xml:space="preserve">
|
||||
<value>Set min thread</value>
|
||||
</data>
|
||||
<data name="Help_retryCount" xml:space="preserve">
|
||||
<value>Set retry times</value>
|
||||
</data>
|
||||
<data name="Help_timeOut" xml:space="preserve">
|
||||
<value>Set timeout for http request(second)</value>
|
||||
</data>
|
||||
<data name="Help_muxSetJson" xml:space="preserve">
|
||||
<value>Set a json file for mux</value>
|
||||
</data>
|
||||
<data name="Help_useKeyFile" xml:space="preserve">
|
||||
<value>Use 16 bytes file as KEY for AES-128 decryption</value>
|
||||
</data>
|
||||
<data name="Help_useKeyBase64" xml:space="preserve">
|
||||
<value>Use Base64 String as KEY for AES-128 decryption</value>
|
||||
</data>
|
||||
<data name="Help_useKeyIV" xml:space="preserve">
|
||||
<value>Use HEX String as IV for AES-128 decryption</value>
|
||||
</data>
|
||||
<data name="Help_downloadRange" xml:space="preserve">
|
||||
<value>Set range for a video</value>
|
||||
</data>
|
||||
<data name="Help_liveRecDur" xml:space="preserve">
|
||||
<value>When the live recording reaches this length, the software will exit automatically(HH:MM:SS)</value>
|
||||
</data>
|
||||
<data name="Help_stopSpeed" xml:space="preserve">
|
||||
<value>Speed below this, retry(KB/s)</value>
|
||||
</data>
|
||||
<data name="Help_maxSpeed" xml:space="preserve">
|
||||
<value>Set max download speed(KB/s)</value>
|
||||
</data>
|
||||
<data name="Help_proxyAddress" xml:space="preserve">
|
||||
<value>Set HTTP/SOCKS5 Proxy, like http://127.0.0.1:8080</value>
|
||||
</data>
|
||||
<data name="Help_enableDelAfterDone" xml:space="preserve">
|
||||
<value>Enable delete clips after download completed</value>
|
||||
</data>
|
||||
<data name="Help_enableMuxFastStart" xml:space="preserve">
|
||||
<value>Enable fast start for mp4</value>
|
||||
</data>
|
||||
<data name="Help_enableBinaryMerge" xml:space="preserve">
|
||||
<value>Enable use binary merge instead of ffmpeg</value>
|
||||
</data>
|
||||
<data name="Help_enableParseOnly" xml:space="preserve">
|
||||
<value>Enable parse only mode</value>
|
||||
</data>
|
||||
<data name="Help_enableAudioOnly" xml:space="preserve">
|
||||
<value>Enable only audio track when mux use ffmpeg</value>
|
||||
</data>
|
||||
<data name="Help_disableDateInfo" xml:space="preserve">
|
||||
<value>Disable write date info when mux use ffmpeg</value>
|
||||
</data>
|
||||
<data name="Help_noMerge" xml:space="preserve">
|
||||
<value>Disable auto merge</value>
|
||||
</data>
|
||||
<data name="Help_noProxy" xml:space="preserve">
|
||||
<value>Disable use system proxy</value>
|
||||
</data>
|
||||
<data name="Help_disableIntegrityCheck" xml:space="preserve">
|
||||
<value>Disable integrity check</value>
|
||||
</data>
|
||||
<data name="Help_registerUrlProtocol" xml:space="preserve">
|
||||
<value>Register m3u8dl URL protocol</value>
|
||||
</data>
|
||||
<data name="Help_unregisterUrlProtocol" xml:space="preserve">
|
||||
<value>Unregister m3u8dl URL protocol</value>
|
||||
</data>
|
||||
<data name="registerUrlProtocolFailed" xml:space="preserve">
|
||||
<value>Register m3u8dl URL protocol failed!</value>
|
||||
</data>
|
||||
<data name="registerUrlProtocolSuccessful" xml:space="preserve">
|
||||
<value>Register m3u8dl URL protocol successfully!</value>
|
||||
</data>
|
||||
<data name="unregisterUrlProtocolFailed" xml:space="preserve">
|
||||
<value>Unregister m3u8dl URL protocol failed!</value>
|
||||
</data>
|
||||
<data name="unregisterUrlProtocolSuccessful" xml:space="preserve">
|
||||
<value>Unregister m3u8dl URL protocol successfully!</value>
|
||||
</data>
|
||||
</root>
|
@@ -183,35 +183,6 @@
|
||||
<data name="hasExternalSubtitleTrack" xml:space="preserve">
|
||||
<value>识别到外挂字幕轨道</value>
|
||||
</data>
|
||||
<data name="helpInfo" xml:space="preserve">
|
||||
<value>N_m3u8DL-CLI.exe <URL|File|JSON> [OPTIONS]
|
||||
|
||||
--workDir Directory 设定程序工作目录
|
||||
--saveName Filename 设定存储文件名(不包括后缀)
|
||||
--baseUrl BaseUrl 设定Baseurl
|
||||
--headers headers 设定请求头,格式 key:value 使用|分割不同的key&value
|
||||
--maxThreads Thread 设定程序的最大线程数(默认为32)
|
||||
--minThreads Thread 设定程序的最小线程数(默认为16)
|
||||
--retryCount Count 设定程序的重试次数(默认为15)
|
||||
--timeOut Sec 设定程序网络请求的超时时间(单位为秒,默认为10秒)
|
||||
--muxSetJson File 使用外部json文件定义混流选项
|
||||
--useKeyFile File 使用外部16字节文件定义AES-128解密KEY
|
||||
--useKeyBase64 Base64String 使用Base64字符串定义AES-128解密KEY
|
||||
--useKeyIV HEXString 使用HEX字符串定义AES-128解密IV
|
||||
--downloadRange Range 仅下载视频的一部分分片或长度
|
||||
--liveRecDur HH:MM:SS 直播录制时,达到此长度自动退出软件
|
||||
--stopSpeed Number 当速度低于此值时,重试(单位为KB/s)
|
||||
--maxSpeed Number 设置下载速度上限(单位为KB/s)
|
||||
--enableDelAfterDone 开启下载后删除临时文件夹的功能
|
||||
--enableMuxFastStart 开启混流mp4的FastStart特性
|
||||
--enableBinaryMerge 开启二进制合并分片
|
||||
--enableParseOnly 开启仅解析模式(程序只进行到meta.json)
|
||||
--enableAudioOnly 合并时仅封装音频轨道
|
||||
--disableDateInfo 关闭混流中的日期写入
|
||||
--noMerge 禁用自动合并
|
||||
--noProxy 不自动使用系统代理
|
||||
--disableIntegrityCheck 不检测分片数量是否完整</value>
|
||||
</data>
|
||||
<data name="invalidM3u8" xml:space="preserve">
|
||||
<value>无效的m3u8</value>
|
||||
</data>
|
||||
@@ -299,4 +270,109 @@
|
||||
<data name="wrtingMeta" xml:space="preserve">
|
||||
<value>写出meta.json</value>
|
||||
</data>
|
||||
<data name="startParsingMpd" xml:space="preserve">
|
||||
<value>开始解析MPD内容...</value>
|
||||
</data>
|
||||
<data name="checkingLast" xml:space="preserve">
|
||||
<value>正在判断尾分片是否有效...</value>
|
||||
</data>
|
||||
<data name="Help_workDir" xml:space="preserve">
|
||||
<value>设定程序工作目录</value>
|
||||
</data>
|
||||
<data name="Help_saveName" xml:space="preserve">
|
||||
<value>设定存储文件名(不包括后缀)</value>
|
||||
</data>
|
||||
<data name="Help_input" xml:space="preserve">
|
||||
<value>链接或文件</value>
|
||||
</data>
|
||||
<data name="Help_baseUrl" xml:space="preserve">
|
||||
<value>设定Baseurl</value>
|
||||
</data>
|
||||
<data name="Help_headers" xml:space="preserve">
|
||||
<value>设定请求头,格式 key:value 使用|分割不同的key&value</value>
|
||||
</data>
|
||||
<data name="Help_maxThreads" xml:space="preserve">
|
||||
<value>设定程序的最大线程数</value>
|
||||
</data>
|
||||
<data name="Help_minThreads" xml:space="preserve">
|
||||
<value>设定程序的最小线程数</value>
|
||||
</data>
|
||||
<data name="Help_retryCount" xml:space="preserve">
|
||||
<value>设定程序的重试次数</value>
|
||||
</data>
|
||||
<data name="Help_timeOut" xml:space="preserve">
|
||||
<value>设定程序网络请求的超时时间(单位为秒)</value>
|
||||
</data>
|
||||
<data name="Help_muxSetJson" xml:space="preserve">
|
||||
<value>使用外部json文件定义混流选项</value>
|
||||
</data>
|
||||
<data name="Help_useKeyFile" xml:space="preserve">
|
||||
<value>使用外部16字节文件定义AES-128解密KEY</value>
|
||||
</data>
|
||||
<data name="Help_useKeyBase64" xml:space="preserve">
|
||||
<value>使用Base64字符串定义AES-128解密KEY</value>
|
||||
</data>
|
||||
<data name="Help_useKeyIV" xml:space="preserve">
|
||||
<value>使用HEX字符串定义AES-128解密IV</value>
|
||||
</data>
|
||||
<data name="Help_downloadRange" xml:space="preserve">
|
||||
<value>仅下载视频的一部分分片或长度</value>
|
||||
</data>
|
||||
<data name="Help_liveRecDur" xml:space="preserve">
|
||||
<value>直播录制时,达到此长度自动退出软件(HH:MM:SS)</value>
|
||||
</data>
|
||||
<data name="Help_stopSpeed" xml:space="preserve">
|
||||
<value>当速度低于此值时,重试(单位为KB/s)</value>
|
||||
</data>
|
||||
<data name="Help_maxSpeed" xml:space="preserve">
|
||||
<value>设置下载速度上限(单位为KB/s)</value>
|
||||
</data>
|
||||
<data name="Help_proxyAddress" xml:space="preserve">
|
||||
<value>设置HTTP/SOCKS5代理, 如 http://127.0.0.1:8080</value>
|
||||
</data>
|
||||
<data name="Help_enableDelAfterDone" xml:space="preserve">
|
||||
<value>开启下载后删除临时文件夹的功能</value>
|
||||
</data>
|
||||
<data name="Help_enableMuxFastStart" xml:space="preserve">
|
||||
<value>开启混流mp4的FastStart特性</value>
|
||||
</data>
|
||||
<data name="Help_enableBinaryMerge" xml:space="preserve">
|
||||
<value>开启二进制合并分片</value>
|
||||
</data>
|
||||
<data name="Help_enableParseOnly" xml:space="preserve">
|
||||
<value>开启仅解析模式(程序只进行到meta.json)</value>
|
||||
</data>
|
||||
<data name="Help_enableAudioOnly" xml:space="preserve">
|
||||
<value>合并时仅封装音频轨道</value>
|
||||
</data>
|
||||
<data name="Help_disableDateInfo" xml:space="preserve">
|
||||
<value>关闭混流中的日期写入</value>
|
||||
</data>
|
||||
<data name="Help_noMerge" xml:space="preserve">
|
||||
<value>禁用自动合并</value>
|
||||
</data>
|
||||
<data name="Help_noProxy" xml:space="preserve">
|
||||
<value>不自动使用系统代理</value>
|
||||
</data>
|
||||
<data name="Help_disableIntegrityCheck" xml:space="preserve">
|
||||
<value>不检测分片数量是否完整</value>
|
||||
</data>
|
||||
<data name="Help_registerUrlProtocol" xml:space="preserve">
|
||||
<value>注册m3u8dl链接协议</value>
|
||||
</data>
|
||||
<data name="Help_unregisterUrlProtocol" xml:space="preserve">
|
||||
<value>取消注册m3u8dl链接协议</value>
|
||||
</data>
|
||||
<data name="registerUrlProtocolFailed" xml:space="preserve">
|
||||
<value>注册m3u8dl链接协议失败!</value>
|
||||
</data>
|
||||
<data name="registerUrlProtocolSuccessful" xml:space="preserve">
|
||||
<value>注册m3u8dl链接协议成功!</value>
|
||||
</data>
|
||||
<data name="unregisterUrlProtocolFailed" xml:space="preserve">
|
||||
<value>取消注册m3u8dl链接协议失败!</value>
|
||||
</data>
|
||||
<data name="unregisterUrlProtocolSuccessful" xml:space="preserve">
|
||||
<value>取消注册m3u8dl链接协议成功!</value>
|
||||
</data>
|
||||
</root>
|
@@ -183,35 +183,6 @@
|
||||
<data name="hasExternalSubtitleTrack" xml:space="preserve">
|
||||
<value>識別到外掛字幕軌道</value>
|
||||
</data>
|
||||
<data name="helpInfo" xml:space="preserve">
|
||||
<value>N_m3u8DL-CLI.exe <URL|File|JSON> [OPTIONS]
|
||||
|
||||
--workDir Directory 設定程序工作目錄
|
||||
--saveName Filename 設定存儲文件名(不包括後綴)
|
||||
--baseUrl BaseUrl 設定Baseurl
|
||||
--headers headers 設定請求頭,格式 key:value 使用|分割不同的key&value
|
||||
--maxThreads Thread 設定程序的最大線程數(默認為32)
|
||||
--minThreads Thread 設定程序的最小線程數(默認為16)
|
||||
--retryCount Count 設定程序的重試次數(默認為15)
|
||||
--timeOut Sec 設定程序網絡請求的超時時間(單位為秒,默認為10秒)
|
||||
--muxSetJson File 使用外部json文件定義混流選項
|
||||
--useKeyFile File 使用外部16字節文件定義AES-128解密KEY
|
||||
--useKeyBase64 Base64String 使用Base64字符串定義AES-128解密KEY
|
||||
--useKeyIV HEXString 使用HEX字符串定義AES-128解密IV
|
||||
--downloadRange Range 僅下載視頻的壹部分分片或長度
|
||||
--liveRecDur HH:MM:SS 直播錄制時,達到此長度自動退出軟件
|
||||
--stopSpeed Number 當速度低於此值時,重試(單位為KB/s)
|
||||
--maxSpeed Number 設置下載速度上限(單位為KB/s)
|
||||
--enableDelAfterDone 開啟下載後刪除臨時文件夾的功能
|
||||
--enableMuxFastStart 開啟混流mp4的FastStart特性
|
||||
--enableBinaryMerge 開啟二進制合並分片
|
||||
--enableParseOnly 開啟僅解析模式(程序只進行到meta.json)
|
||||
--enableAudioOnly 合並時僅封裝音頻軌道
|
||||
--disableDateInfo 關閉混流中的日期寫入
|
||||
--noMerge 禁用自動合並
|
||||
--noProxy 不自動使用系統代理
|
||||
--disableIntegrityCheck 不檢測分片數量是否完整</value>
|
||||
</data>
|
||||
<data name="invalidM3u8" xml:space="preserve">
|
||||
<value>無效的m3u8</value>
|
||||
</data>
|
||||
@@ -299,4 +270,109 @@
|
||||
<data name="wrtingMeta" xml:space="preserve">
|
||||
<value>寫出meta.json</value>
|
||||
</data>
|
||||
<data name="startParsingMpd" xml:space="preserve">
|
||||
<value>開始解析MPD內容...</value>
|
||||
</data>
|
||||
<data name="checkingLast" xml:space="preserve">
|
||||
<value>正在判斷尾分片是否有效...</value>
|
||||
</data>
|
||||
<data name="Help_workDir" xml:space="preserve">
|
||||
<value>設定程式工作目錄</value>
|
||||
</data>
|
||||
<data name="Help_saveName" xml:space="preserve">
|
||||
<value>設定存儲文件名(不包括後綴)</value>
|
||||
</data>
|
||||
<data name="Help_input" xml:space="preserve">
|
||||
<value>連結或檔案</value>
|
||||
</data>
|
||||
<data name="Help_baseUrl" xml:space="preserve">
|
||||
<value>設定Baseurl</value>
|
||||
</data>
|
||||
<data name="Help_headers" xml:space="preserve">
|
||||
<value>設定請求頭,格式 key:value 使用|分割不同的key&value</value>
|
||||
</data>
|
||||
<data name="Help_maxThreads" xml:space="preserve">
|
||||
<value>設定程式的最大線程數</value>
|
||||
</data>
|
||||
<data name="Help_minThreads" xml:space="preserve">
|
||||
<value>設定程式的最小線程數</value>
|
||||
</data>
|
||||
<data name="Help_retryCount" xml:space="preserve">
|
||||
<value>設定程式的重試次數</value>
|
||||
</data>
|
||||
<data name="Help_timeOut" xml:space="preserve">
|
||||
<value>設定程式網絡請求的超時時間(單位為秒)</value>
|
||||
</data>
|
||||
<data name="Help_muxSetJson" xml:space="preserve">
|
||||
<value>使用外部json文件定義混流選項</value>
|
||||
</data>
|
||||
<data name="Help_useKeyFile" xml:space="preserve">
|
||||
<value>使用外部16字節文件定義AES-128解密KEY</value>
|
||||
</data>
|
||||
<data name="Help_useKeyBase64" xml:space="preserve">
|
||||
<value>使用Base64字符串定義AES-128解密KEY</value>
|
||||
</data>
|
||||
<data name="Help_useKeyIV" xml:space="preserve">
|
||||
<value>使用HEX字符串定義AES-128解密IV</value>
|
||||
</data>
|
||||
<data name="Help_downloadRange" xml:space="preserve">
|
||||
<value>僅下載視頻的壹部分分片或長度</value>
|
||||
</data>
|
||||
<data name="Help_liveRecDur" xml:space="preserve">
|
||||
<value>直播錄制時,達到此長度自動退出軟件(HH:MM:SS)</value>
|
||||
</data>
|
||||
<data name="Help_stopSpeed" xml:space="preserve">
|
||||
<value>當速度低於此值時,重試(單位為KB/s)</value>
|
||||
</data>
|
||||
<data name="Help_maxSpeed" xml:space="preserve">
|
||||
<value>設置下載速度上限(單位為KB/s)</value>
|
||||
</data>
|
||||
<data name="Help_proxyAddress" xml:space="preserve">
|
||||
<value>設置HTTP/SOCKS5代理, 如 http://127.0.0.1:8080</value>
|
||||
</data>
|
||||
<data name="Help_enableDelAfterDone" xml:space="preserve">
|
||||
<value>開啟下載後刪除臨時文件夾的功能</value>
|
||||
</data>
|
||||
<data name="Help_enableMuxFastStart" xml:space="preserve">
|
||||
<value>開啟混流mp4的FastStart特性</value>
|
||||
</data>
|
||||
<data name="Help_enableBinaryMerge" xml:space="preserve">
|
||||
<value>開啟二進制合並分片</value>
|
||||
</data>
|
||||
<data name="Help_enableParseOnly" xml:space="preserve">
|
||||
<value>開啟僅解析模式(程式只進行到meta.json)</value>
|
||||
</data>
|
||||
<data name="Help_enableAudioOnly" xml:space="preserve">
|
||||
<value>合並時僅封裝音頻軌道</value>
|
||||
</data>
|
||||
<data name="Help_disableDateInfo" xml:space="preserve">
|
||||
<value>關閉混流中的日期寫入</value>
|
||||
</data>
|
||||
<data name="Help_noMerge" xml:space="preserve">
|
||||
<value>禁用自動合並</value>
|
||||
</data>
|
||||
<data name="Help_noProxy" xml:space="preserve">
|
||||
<value>不自動使用系統代理</value>
|
||||
</data>
|
||||
<data name="Help_disableIntegrityCheck" xml:space="preserve">
|
||||
<value>不檢測分片數量是否完整</value>
|
||||
</data>
|
||||
<data name="Help_registerUrlProtocol" xml:space="preserve">
|
||||
<value>注册m3u8dl連結協定</value>
|
||||
</data>
|
||||
<data name="Help_unregisterUrlProtocol" xml:space="preserve">
|
||||
<value>取消注册m3u8dl連結協定</value>
|
||||
</data>
|
||||
<data name="registerUrlProtocolFailed" xml:space="preserve">
|
||||
<value>注册m3u8dl連結協定失敗!</value>
|
||||
</data>
|
||||
<data name="registerUrlProtocolSuccessful" xml:space="preserve">
|
||||
<value>注册m3u8dl連結協定成功!</value>
|
||||
</data>
|
||||
<data name="unregisterUrlProtocolFailed" xml:space="preserve">
|
||||
<value>取消注册m3u8dl連結協定失敗!</value>
|
||||
</data>
|
||||
<data name="unregisterUrlProtocolSuccessful" xml:space="preserve">
|
||||
<value>取消注册m3u8dl連結協定成功!</value>
|
||||
</data>
|
||||
</root>
|
108
README.md
108
README.md
@@ -13,20 +13,23 @@
|
||||
|
||||
|
||||
# [ENGLISH VERSION](https://github.com/nilaoda/N_m3u8DL-CLI/blob/master/README_ENG.md)
|
||||
|
||||
# 下载使用
|
||||
* 发行版: https://github.com/nilaoda/N_m3u8DL-CLI/releases
|
||||
* 自动构建版`(供测试)`: https://github.com/nilaoda/N_m3u8DL-CLI/actions
|
||||
|
||||
# 关于开源
|
||||
本项目已与2019年10月9日开源,采用MIT许可证,各取所需。
|
||||
本项目已于2019年10月9日开源,采用MIT许可证,各取所需。
|
||||
|
||||
# 关于跨平台
|
||||
~~本项目已通过`.NET Core`实现跨平台,理论支持Mac、Linux、Windows等平台,请移步:https://github.com/nilaoda/N_m3u8DL-CLI_Core~~
|
||||
|
||||
暂时放弃跨平台(很多API需要重写才能实现功能,日后有空再维护)
|
||||
未来可期
|
||||
|
||||
# N_m3u8DL-CLI
|
||||
一个**简单易用的**m3u8下载器,下载地址:https://github.com/nilaoda/N_m3u8DL-CLI/releases
|
||||
|
||||
支持下载m3u8链接或文件为`mp4`或`ts`格式,并提供丰富的命令行选项。
|
||||
* **不支持**优酷视频解密
|
||||
* **不支持**气球云视频解密
|
||||
* 支持`AES-128-CBC`加密自动解密
|
||||
* 支持多线程下载
|
||||
* 支持下载限速
|
||||
@@ -39,7 +42,9 @@
|
||||
* 支持下载路径为网络驱动器的情况
|
||||
* 支持下载外挂字幕轨道、音频轨道
|
||||
* 支持仅合并为音频
|
||||
* 自动使用系统代理(可禁止)
|
||||
* 支持设置特定http代理
|
||||
* 支持自动使用系统代理(默认行为, 可禁止)
|
||||
* 支持m3u8dl链接协议(通过web链接调用本机客户端)
|
||||
* 提供SimpleG简易的`GUI`生成常用参数
|
||||
|
||||
|
||||
@@ -48,37 +53,76 @@
|
||||
|
||||
# 命令行选项
|
||||
```
|
||||
N_m3u8DL-CLI.exe <URL|JSON|FILE> [OPTIONS]
|
||||
N_m3u8DL-CLI
|
||||
|
||||
--workDir Directory 设定程序工作目录
|
||||
--saveName Filename 设定存储文件名(不包括后缀)
|
||||
--baseUrl BaseUrl 设定Baseurl
|
||||
--headers headers 设定请求头,格式 key:value 使用|分割不同的key&value
|
||||
--maxThreads Thread 设定程序的最大线程数(默认为32)
|
||||
--minThreads Thread 设定程序的最小线程数(默认为16)
|
||||
--retryCount Count 设定程序的重试次数(默认为15)
|
||||
--timeOut Sec 设定程序网络请求的超时时间(单位为秒,默认为10秒)
|
||||
--muxSetJson File 使用外部json文件定义混流选项
|
||||
--useKeyFile File 使用外部16字节文件定义AES-128解密KEY
|
||||
--useKeyBase64 Base64String 使用Base64字符串定义AES-128解密KEY
|
||||
--useKeyIV HEXString 使用HEX字符串定义AES-128解密IV
|
||||
--downloadRange Range 仅下载视频的一部分分片或长度
|
||||
--liveRecDur HH:MM:SS 直播录制时,达到此长度自动退出软件
|
||||
--stopSpeed Number 当速度低于此值时,重试(单位为KB/s)
|
||||
--maxSpeed Number 设置下载速度上限(单位为KB/s)
|
||||
--enableDelAfterDone 开启下载后删除临时文件夹的功能
|
||||
--enableMuxFastStart 开启混流mp4的FastStart特性
|
||||
--enableBinaryMerge 开启二进制合并分片
|
||||
--enableParseOnly 开启仅解析模式(程序只进行到meta.json)
|
||||
--enableAudioOnly 合并时仅封装音频轨道
|
||||
--disableDateInfo 关闭混流中的日期写入
|
||||
--noMerge 禁用自动合并
|
||||
--noProxy 不自动使用系统代理
|
||||
--disableIntegrityCheck 不检测分片数量是否完整
|
||||
USAGE:
|
||||
|
||||
N_m3u8DL-CLI <URL|JSON|FILE> [OPTIONS]
|
||||
|
||||
OPTIONS:
|
||||
|
||||
--workDir 设定程序工作目录
|
||||
--saveName 设定存储文件名(不包括后缀)
|
||||
--baseUrl 设定Baseurl
|
||||
--headers 设定请求头,格式 key:value 使用|分割不同的key&value
|
||||
--maxThreads (Default: 32) 设定程序的最大线程数
|
||||
--minThreads (Default: 16) 设定程序的最小线程数
|
||||
--retryCount (Default: 15) 设定程序的重试次数
|
||||
--timeOut (Default: 10) 设定程序网络请求的超时时间(单位为秒)
|
||||
--muxSetJson 使用外部json文件定义混流选项
|
||||
--useKeyFile 使用外部16字节文件定义AES-128解密KEY
|
||||
--useKeyBase64 使用Base64字符串定义AES-128解密KEY
|
||||
--useKeyIV 使用HEX字符串定义AES-128解密IV
|
||||
--downloadRange 仅下载视频的一部分分片或长度
|
||||
--liveRecDur 直播录制时,达到此长度自动退出软件(HH:MM:SS)
|
||||
--stopSpeed 当速度低于此值时,重试(单位为KB/s)
|
||||
--maxSpeed 设置下载速度上限(单位为KB/s)
|
||||
--proxyAddress 设置HTTP/SOCKS5代理, 如 http://127.0.0.1:8080
|
||||
--enableDelAfterDone 开启下载后删除临时文件夹的功能
|
||||
--enableMuxFastStart 开启混流mp4的FastStart特性
|
||||
--enableBinaryMerge 开启二进制合并分片
|
||||
--enableParseOnly 开启仅解析模式(程序只进行到meta.json)
|
||||
--enableAudioOnly 合并时仅封装音频轨道
|
||||
--disableDateInfo 关闭混流中的日期写入
|
||||
--disableIntegrityCheck 不检测分片数量是否完整
|
||||
--noMerge 禁用自动合并
|
||||
--noProxy 不自动使用系统代理
|
||||
--registerUrlProtocol 注册m3u8dl链接协议
|
||||
--unregisterUrlProtocol 取消注册m3u8dl链接协议
|
||||
--enableChaCha20 enableChaCha20
|
||||
--chaCha20KeyBase64 ChaCha20KeyBase64
|
||||
--chaCha20NonceBase64 ChaCha20NonceBase64
|
||||
--help Display this help screen.
|
||||
--version Display version information.
|
||||
```
|
||||
|
||||
# 关于`m3u8dl://`协议
|
||||
新增命令行参数:
|
||||
```
|
||||
--registerUrlProtocol 注册m3u8dl链接协议
|
||||
--unregisterUrlProtocol 取消注册m3u8dl链接协议
|
||||
```
|
||||
|
||||
URI格式:
|
||||
```
|
||||
m3u8dl://<base64编码的客户端命令行文本>
|
||||
```
|
||||
|
||||
URI示例:
|
||||
```
|
||||
m3u8dl://Imh0dHBzOi8vZXhhbXBsZS5jb20vYWJjLm0zdTgiIC0td29ya0RpciAiJVVTRVJQUk9GSUxFJVxEb3dubG9hZHNcbTN1OGRsIiAtLXNhdmVOYW1lICJhYmMiIC0tZW5hYmxlRGVsQWZ0ZXJEb25lIC0tZGlzYWJsZURhdGVJbmZvIC0tbm9Qcm94eQ==
|
||||
```
|
||||
|
||||
URI解码结果:
|
||||
```
|
||||
"https://example.com/abc.m3u8" --workDir "%USERPROFILE%\Downloads\m3u8dl" --saveName "abc" --enableDelAfterDone --disableDateInfo --noProxy
|
||||
```
|
||||
|
||||
# 用户文档
|
||||
https://nilaoda.github.io/N_m3u8DL-CLI/
|
||||
|
||||
# 聊聊
|
||||
https://discord.gg/W5tvcRJDPs
|
||||
|
||||
# 赞赏
|
||||
https://nilaoda.github.io/N_m3u8DL-CLI/source/images/alipay.png
|
||||

|
||||
|
104
README_ENG.md
104
README_ENG.md
@@ -8,10 +8,10 @@
|
||||
╚═╝ ╚═══╝╚══════╝╚═╝ ╚═╝╚═════╝ ╚═════╝ ╚════╝ ╚═════╝ ╚══════╝ ╚═════╝╚══════╝╚═╝
|
||||
|
||||
```
|
||||
This is a m3u8 downloader.
|
||||
This is an m3u8 downloader.
|
||||
## Summary
|
||||
Supports:
|
||||
* Auto deceypt for `AES-128-CBC`
|
||||
* Auto decrypt for `AES-128-CBC`
|
||||
* `Master List`
|
||||
* Live stream recording(`BETA`)
|
||||
* Customize HTTP headers
|
||||
@@ -20,8 +20,8 @@ Supports:
|
||||
* Network driver on Windows OS
|
||||
* Alternative audio/video track
|
||||
* Mux without video track
|
||||
* Auto use system proxy
|
||||
* Optimization for Chinese streaming platform
|
||||
* Custom HTTP proxy or Use system proxy
|
||||
* Optimization for Chinese streaming platforms
|
||||
|
||||

|
||||
|
||||
@@ -30,33 +30,75 @@ Supports:
|
||||
|
||||
## Options
|
||||
```
|
||||
N_m3u8DL-CLI.exe <URL|JSON|FILE> [OPTIONS]
|
||||
N_m3u8DL-CLI
|
||||
|
||||
--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
|
||||
USAGE:
|
||||
|
||||
N_m3u8DL-CLI <URL|JSON|FILE> [OPTIONS]
|
||||
|
||||
OPTIONS:
|
||||
|
||||
--workDir Set work dir (Video will be here)
|
||||
--saveName Set save name(Exclude extention)
|
||||
--baseUrl Set Baseurl
|
||||
--headers Set HTTP headers,format: key:value use | split all
|
||||
key&value
|
||||
--maxThreads (Default: 32) Set max thread
|
||||
--minThreads (Default: 16) Set min thread
|
||||
--retryCount (Default: 15) Set retry times
|
||||
--timeOut (Default: 10) Set timeout for http request(second)
|
||||
--muxSetJson Set a json file for mux
|
||||
--useKeyFile Use 16 bytes file as KEY for AES-128 decryption
|
||||
--useKeyBase64 Use Base64 String as KEY for AES-128 decryption
|
||||
--useKeyIV Use HEX String as IV for AES-128 decryption
|
||||
--downloadRange Set range for a video
|
||||
--liveRecDur When the live recording reaches this length, the
|
||||
software will exit automatically(HH:MM:SS)
|
||||
--stopSpeed Speed below this, retry(KB/s)
|
||||
--maxSpeed Set max download speed(KB/s)
|
||||
--proxyAddress Set HTTP/SOCKS5 Proxy, like http://127.0.0.1:8080
|
||||
--enableDelAfterDone Enable delete clips after download completed
|
||||
--enableMuxFastStart Enable fast start for mp4
|
||||
--enableBinaryMerge Enable use binary merge instead of ffmpeg
|
||||
--enableParseOnly Enable parse only mode
|
||||
--enableAudioOnly Enable only audio track when mux use ffmpeg
|
||||
--disableDateInfo Disable write date info when mux use ffmpeg
|
||||
--disableIntegrityCheck Disable integrity check
|
||||
--noMerge Disable auto merge
|
||||
--noProxy Disable use system proxy
|
||||
--registerUrlProtocol Register m3u8dl URL protocol
|
||||
--unregisterUrlProtocol Unregister m3u8dl URL protocol
|
||||
--enableChaCha20 enableChaCha20
|
||||
--chaCha20KeyBase64 ChaCha20KeyBase64
|
||||
--chaCha20NonceBase64 ChaCha20NonceBase64
|
||||
--help Display this help screen.
|
||||
--version Display version information.
|
||||
```
|
||||
|
||||
|
||||
## About `m3u8dl://`
|
||||
New commandline options:
|
||||
```
|
||||
--registerUrlProtocol Register m3u8dl URL protocol
|
||||
--unregisterUrlProtocol Unregister m3u8dl URL protocol
|
||||
```
|
||||
|
||||
URI Format:
|
||||
```
|
||||
m3u8dl://<base64 encoded params>
|
||||
```
|
||||
|
||||
URI Example:
|
||||
```
|
||||
m3u8dl://Imh0dHBzOi8vZXhhbXBsZS5jb20vYWJjLm0zdTgiIC0td29ya0RpciAiJVVTRVJQUk9GSUxFJVxEb3dubG9hZHNcbTN1OGRsIiAtLXNhdmVOYW1lICJhYmMiIC0tZW5hYmxlRGVsQWZ0ZXJEb25lIC0tZGlzYWJsZURhdGVJbmZvIC0tbm9Qcm94eQ==
|
||||
```
|
||||
|
||||
URI Decode Result:
|
||||
```
|
||||
"https://example.com/abc.m3u8" --workDir "%USERPROFILE%\Downloads\m3u8dl" --saveName "abc" --enableDelAfterDone --disableDateInfo --noProxy
|
||||
```
|
||||
|
||||
## Document
|
||||
https://nilaoda.github.io/N_m3u8DL-CLI/
|
||||
https://nilaoda.github.io/N_m3u8DL-CLI/
|
||||
|
||||
## Chit-chat
|
||||
https://discord.gg/W5tvcRJDPs
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user