You've already forked N_m3u8DL-CLI
mirror of
https://github.com/nilaoda/N_m3u8DL-CLI
synced 2025-09-11 16:00:49 +02:00
Compare commits
30 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
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 |
@@ -368,6 +368,8 @@ namespace N_m3u8DL_CLI
|
||||
//有MAP文件,一般为mp4,采取默认动作
|
||||
if(File.Exists(DownDir + "\\Part_0\\!MAP.ts"))
|
||||
MuxFormat = "mp4";
|
||||
if (isVTT)
|
||||
MuxFormat = "vtt";
|
||||
|
||||
if (Global.AUDIO_TYPE != "")
|
||||
MuxFormat = Global.AUDIO_TYPE;
|
||||
@@ -528,6 +530,8 @@ namespace N_m3u8DL_CLI
|
||||
//有MAP文件,一般为mp4,采取默认动作
|
||||
if (File.Exists(DownDir + "\\!MAP.ts"))
|
||||
MuxFormat = "mp4";
|
||||
if (isVTT)
|
||||
MuxFormat = "vtt";
|
||||
Global.CombineMultipleFilesIntoSingleFile(Global.GetFiles(DownDir, ".ts"), FFmpeg.OutPutPath + $".{MuxFormat}");
|
||||
}
|
||||
else
|
||||
|
@@ -24,15 +24,17 @@ namespace N_m3u8DL_CLI
|
||||
public static string AUDIO_TYPE = "";
|
||||
public static bool HadReadInfo = false;
|
||||
private static bool noProxy = false;
|
||||
private static string useProxyAddress = "";
|
||||
|
||||
public static bool ShouldStop { get => shouldStop; set => shouldStop = value; }
|
||||
public static bool NoProxy { get => noProxy; set => noProxy = value; }
|
||||
public static string UseProxyAddress { get => useProxyAddress; set => useProxyAddress = value; }
|
||||
|
||||
|
||||
/*===============================================================================*/
|
||||
static Version ver = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
|
||||
static string nowVer = $"{ver.Major}.{ver.Minor}.{ver.Build}";
|
||||
static string nowDate = "20201229";
|
||||
static string nowDate = "20210201";
|
||||
public static void WriteInit()
|
||||
{
|
||||
Console.Clear();
|
||||
@@ -109,7 +111,16 @@ namespace N_m3u8DL_CLI
|
||||
reProcess:
|
||||
HttpWebRequest webRequest = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(url);
|
||||
webRequest.Method = "GET";
|
||||
if (NoProxy) webRequest.Proxy = null;
|
||||
if (NoProxy)
|
||||
{
|
||||
webRequest.Proxy = null;
|
||||
}
|
||||
else if (UseProxyAddress != "")
|
||||
{
|
||||
WebProxy proxy = new WebProxy(UseProxyAddress);
|
||||
//proxy.Credentials = new NetworkCredential(username, password);
|
||||
webRequest.Proxy = proxy;
|
||||
}
|
||||
webRequest.UserAgent = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36";
|
||||
webRequest.Accept = "*/*";
|
||||
webRequest.Headers.Add("Accept-Encoding", "gzip, deflate, br");
|
||||
@@ -370,7 +381,16 @@ namespace N_m3u8DL_CLI
|
||||
string redirectUrl;
|
||||
WebRequest myRequest = WebRequest.Create(url);
|
||||
myRequest.Timeout = timeout;
|
||||
if (NoProxy) myRequest.Proxy = null;
|
||||
if (NoProxy)
|
||||
{
|
||||
myRequest.Proxy = null;
|
||||
}
|
||||
else if (UseProxyAddress != "")
|
||||
{
|
||||
WebProxy proxy = new WebProxy(UseProxyAddress);
|
||||
//proxy.Credentials = new NetworkCredential(username, password);
|
||||
myRequest.Proxy = proxy;
|
||||
}
|
||||
//添加headers
|
||||
if (headers != "")
|
||||
{
|
||||
@@ -424,7 +444,16 @@ namespace N_m3u8DL_CLI
|
||||
req.Timeout = timeOut;
|
||||
req.ReadWriteTimeout = timeOut; //重要
|
||||
req.AllowAutoRedirect = false; //手动处理重定向,否则会丢失Referer
|
||||
if (NoProxy) req.Proxy = null;
|
||||
if (NoProxy)
|
||||
{
|
||||
req.Proxy = null;
|
||||
}
|
||||
else if (UseProxyAddress != "")
|
||||
{
|
||||
WebProxy proxy = new WebProxy(UseProxyAddress);
|
||||
//proxy.Credentials = new NetworkCredential(username, password);
|
||||
req.Proxy = proxy;
|
||||
}
|
||||
req.Headers.Add("Accept-Encoding", "gzip, deflate");
|
||||
req.Accept = "*/*";
|
||||
req.UserAgent = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36";
|
||||
@@ -529,7 +558,16 @@ namespace N_m3u8DL_CLI
|
||||
request.AllowAutoRedirect = false; //手动处理重定向,否则会丢失Referer
|
||||
request.KeepAlive = false;
|
||||
request.Method = "GET";
|
||||
if (NoProxy) request.Proxy = null;
|
||||
if (NoProxy)
|
||||
{
|
||||
request.Proxy = null;
|
||||
}
|
||||
else if (UseProxyAddress != "")
|
||||
{
|
||||
WebProxy proxy = new WebProxy(UseProxyAddress);
|
||||
//proxy.Credentials = new NetworkCredential(username, password);
|
||||
request.Proxy = proxy;
|
||||
}
|
||||
if (url.Contains("data.video.iqiyi.com"))
|
||||
request.UserAgent = "QYPlayer/Android/4.4.5;NetType/3G;QTP/1.1.4.3";
|
||||
else if (url.Contains("pcvideo") && url.Contains(".titan.mgtv.com"))
|
||||
@@ -539,6 +577,10 @@ namespace N_m3u8DL_CLI
|
||||
request.Referer = "https://www.mgtv.com";
|
||||
request.Headers.Add("Cookie", "MQGUID");
|
||||
}
|
||||
else if (url.Contains(".xboku.com/")) //独播库
|
||||
{
|
||||
request.Referer = "https://my.duboku.vip/static/player/videojs.html";
|
||||
}
|
||||
else
|
||||
request.UserAgent = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36";
|
||||
//下载部分字节
|
||||
@@ -664,13 +706,13 @@ namespace N_m3u8DL_CLI
|
||||
}
|
||||
else if (137 == u[0] && 80 == u[1] && 78 == u[2] && 71 == u[3])
|
||||
{
|
||||
//确定是PNG但是需要手动查询结尾标记(0x60 0x82 0x47)
|
||||
//确定是PNG但是需要手动查询结尾标记 0x47 出现两次
|
||||
int skip = 0;
|
||||
for (int i = 4; i < u.Length - 3; i++)
|
||||
for (int i = 4; i < u.Length - 188 * 2; i++)
|
||||
{
|
||||
if (u[i] == 0x60 && u[i + 1] == 0x82 && u[i + 2] == 0x47)
|
||||
if (u[i] == 0x47 && u[i + 188] == 0x47 && u[i + 188 + 188] == 0x47)
|
||||
{
|
||||
skip = i + 2;
|
||||
skip = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1106,7 +1148,16 @@ namespace N_m3u8DL_CLI
|
||||
protected override WebRequest GetWebRequest(Uri address)
|
||||
{
|
||||
var wr = (HttpWebRequest)base.GetWebRequest(address);
|
||||
if (NoProxy) wr.Proxy = null;
|
||||
if (NoProxy)
|
||||
{
|
||||
wr.Proxy = null;
|
||||
}
|
||||
else if (UseProxyAddress != "")
|
||||
{
|
||||
WebProxy proxy = new WebProxy(UseProxyAddress);
|
||||
//proxy.Credentials = new NetworkCredential(username, password);
|
||||
wr.Proxy = proxy;
|
||||
}
|
||||
if (setRange)
|
||||
wr.AddRange(this.from, this.to);
|
||||
if (setTimeout)
|
||||
|
@@ -4,6 +4,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
@@ -61,14 +62,18 @@ namespace N_m3u8DL_CLI
|
||||
|
||||
void ExtractInitialization(XmlNode source)
|
||||
{
|
||||
var initialization = source.SelectSingleNode("//ns:Initialization", nsMgr);
|
||||
var initialization = source.SelectSingleNode("ns:Initialization", nsMgr);
|
||||
if (initialization != null)
|
||||
{
|
||||
MultisegmentInfo["InitializationUrl"] = ((XmlElement)initialization).GetAttribute("sourceURL");
|
||||
if (((XmlElement)initialization).HasAttribute("range"))
|
||||
{
|
||||
MultisegmentInfo["InitializationUrl"] += "$$Range=" + ((XmlElement)initialization).GetAttribute("range");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var segmentList = Period.SelectSingleNode("//ns:SegmentList", nsMgr);
|
||||
var segmentList = Period.SelectSingleNode("ns:SegmentList", nsMgr);
|
||||
if (segmentList != null)
|
||||
{
|
||||
ExtractCommon(segmentList);
|
||||
@@ -77,7 +82,14 @@ namespace N_m3u8DL_CLI
|
||||
MultisegmentInfo["SegmentUrls"] = new List<string>();
|
||||
foreach (XmlElement segment in segmentUrlsE)
|
||||
{
|
||||
MultisegmentInfo["SegmentUrls"].Add(segment.GetAttribute("media"));
|
||||
if (segment.HasAttribute("mediaRange"))
|
||||
{
|
||||
MultisegmentInfo["SegmentUrls"].Add("$$Range=" + segment.GetAttribute("mediaRange"));
|
||||
}
|
||||
else
|
||||
{
|
||||
MultisegmentInfo["SegmentUrls"].Add(segment.GetAttribute("media"));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -205,13 +217,14 @@ namespace N_m3u8DL_CLI
|
||||
{
|
||||
mpdBaseUrl += "/";
|
||||
}
|
||||
baseUrl = mpdBaseUrl + baseUrl;
|
||||
baseUrl = CombineURL(mpdBaseUrl, baseUrl);
|
||||
}
|
||||
var representationId = GetAttribute("id");
|
||||
var lang = GetAttribute("lang");
|
||||
var bandwidth = IntOrNull(GetAttribute("bandwidth"));
|
||||
var f = new Dictionary<string, dynamic>
|
||||
{
|
||||
["ContentType"] = contentType,
|
||||
["FormatId"] = representationId,
|
||||
["ManifestUrl"] = mpdUrl,
|
||||
["Width"] = IntOrNull(GetAttribute("width")),
|
||||
@@ -436,6 +449,10 @@ namespace N_m3u8DL_CLI
|
||||
if (representationMsInfo.ContainsKey("InitializationUrl"))
|
||||
{
|
||||
f["InitializationUrl"] = representationMsInfo["InitializationUrl"];
|
||||
if (f["InitializationUrl"].StartsWith("$$Range"))
|
||||
{
|
||||
f["InitializationUrl"] = CombineURL(baseUrl, f["InitializationUrl"]);
|
||||
}
|
||||
f["Fragments"] = representationMsInfo["Fragments"];
|
||||
}
|
||||
}
|
||||
@@ -452,11 +469,11 @@ namespace N_m3u8DL_CLI
|
||||
}
|
||||
|
||||
//处理同一ID分散在不同Period的情况
|
||||
if (formatList.Any(_f => _f["FormatId"] == f["FormatId"] && _f["Width"] == f["Width"]))
|
||||
if (formatList.Any(_f => _f["FormatId"] == f["FormatId"] && _f["Width"] == f["Width"] && _f["ContentType"] == f["ContentType"]))
|
||||
{
|
||||
for (int i = 0; i < formatList.Count; i++)
|
||||
{
|
||||
if (formatList[i]["FormatId"] == f["FormatId"] && formatList[i]["Width"] == f["Width"])
|
||||
if (formatList[i]["FormatId"] == f["FormatId"] && formatList[i]["Width"] == f["Width"] && formatList[i]["ContentType"] == f["ContentType"])
|
||||
{
|
||||
formatList[i]["Fragments"].AddRange(f["Fragments"]);
|
||||
break;
|
||||
@@ -486,14 +503,14 @@ namespace N_m3u8DL_CLI
|
||||
var audioLangList = new List<string>();
|
||||
formatList.ForEach(f =>
|
||||
{
|
||||
if (f["Width"] == -1 && !audioLangList.Contains(f["Language"])) audioLangList.Add(f["Language"]);
|
||||
if (f["ContentType"] == "audio" && !audioLangList.Contains(f["Language"])) audioLangList.Add(f["Language"]);
|
||||
});
|
||||
|
||||
if (audioLangList.Count > 1)
|
||||
{
|
||||
string Stringify(Dictionary<string, dynamic> f)
|
||||
{
|
||||
var type = f["Width"] == -1 && f["Height"] == -1 ? "Audio" : "Video";
|
||||
var type = f["ContentType"] == "aduio" ? "Audio" : "Video";
|
||||
var res = type == "Video" ? $"[{f["Width"]}x{f["Height"]}]" : "";
|
||||
var id = $"[{f["FormatId"]}] ";
|
||||
var tbr = $"[{((int)f["Tbr"]).ToString().PadLeft(4)} Kbps] ";
|
||||
@@ -504,6 +521,7 @@ namespace N_m3u8DL_CLI
|
||||
return $"{type} => {id}{tbr}{asr}{fps}{lang}{codecs}{res}";
|
||||
}
|
||||
|
||||
var startCursorIndex = LOGGER.CursorIndex;
|
||||
for (int i = 0; i < formatList.Count; i++)
|
||||
{
|
||||
Console.WriteLine("".PadRight(13) + $"[{i.ToString().PadLeft(2)}]. {Stringify(formatList[i])}");
|
||||
@@ -515,6 +533,12 @@ namespace N_m3u8DL_CLI
|
||||
var input = Console.ReadLine();
|
||||
LOGGER.CursorIndex += 2;
|
||||
Console.CursorVisible = false;
|
||||
for (int i = startCursorIndex; i < LOGGER.CursorIndex; i++)
|
||||
{
|
||||
Console.SetCursorPosition(0, i);
|
||||
Console.Write("".PadRight(300));
|
||||
}
|
||||
LOGGER.CursorIndex = startCursorIndex;
|
||||
if (!string.IsNullOrEmpty(input))
|
||||
{
|
||||
bestVideo = new Dictionary<string, dynamic>() { ["Tbr"] = 0 };
|
||||
@@ -523,7 +547,7 @@ namespace N_m3u8DL_CLI
|
||||
{
|
||||
var n = 0;
|
||||
int.TryParse(index, out n);
|
||||
if (formatList[n]["Width"] == -1)
|
||||
if (formatList[n]["ContentType"] == "audio")
|
||||
{
|
||||
bestAudio = formatList[n];
|
||||
}
|
||||
@@ -625,7 +649,7 @@ namespace N_m3u8DL_CLI
|
||||
sb.AppendLine("#CREATED-BY:N_m3u8DL-CLI");
|
||||
|
||||
//Video
|
||||
if (f["Width"] != -1 && f["Height"] != -1)
|
||||
if (f["ContentType"] != "audio")
|
||||
{
|
||||
sb.AppendLine($"#EXT-VIDEO-WIDTH:{f["Width"]}");
|
||||
sb.AppendLine($"#EXT-VIDEO-HEIGHT:{f["Height"]}");
|
||||
@@ -635,17 +659,74 @@ namespace N_m3u8DL_CLI
|
||||
sb.AppendLine($"#EXT-TBR:{f["Tbr"]}");
|
||||
if (f.ContainsKey("InitializationUrl"))
|
||||
{
|
||||
sb.AppendLine($"#EXT-X-MAP:URI=\"{f["InitializationUrl"]}\"");
|
||||
string initUrl = f["InitializationUrl"];
|
||||
if (Regex.IsMatch(initUrl, "\\$\\$Range=(\\d+)-(\\d+)"))
|
||||
{
|
||||
var match = Regex.Match(initUrl, "\\$\\$Range=(\\d+)-(\\d+)");
|
||||
string rangeStr = match.Value;
|
||||
long start = Convert.ToInt64(match.Groups[1].Value);
|
||||
long end = Convert.ToInt64(match.Groups[2].Value);
|
||||
sb.AppendLine($"#EXT-X-MAP:URI=\"{initUrl.Replace(rangeStr, "")}\",BYTERANGE=\"{end + 1 - start}@{start}\"");
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.AppendLine($"#EXT-X-MAP:URI=\"{initUrl}\"");
|
||||
}
|
||||
}
|
||||
sb.AppendLine("#EXT-X-KEY:METHOD=PLZ-KEEP-RAW,URI=\"None\""); //使下载器使用二进制合并
|
||||
|
||||
List<Dictionary<string, dynamic>> fragments = f["Fragments"];
|
||||
|
||||
//检测最后一片的有效性
|
||||
if (fragments.Count > 1)
|
||||
{
|
||||
bool checkValid(string url)
|
||||
{
|
||||
try
|
||||
{
|
||||
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(new Uri(url));
|
||||
request.Timeout = 120000;
|
||||
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
|
||||
if (((int)response.StatusCode).ToString().StartsWith("2")) return true;
|
||||
else return false;
|
||||
}
|
||||
catch (Exception) { return false; }
|
||||
}
|
||||
|
||||
var last = fragments.Last();
|
||||
var secondToLast = fragments[fragments.Count - 2];
|
||||
var urlLast = last.ContainsKey("url") ? last["url"] : last["path"];
|
||||
var urlSecondToLast = secondToLast.ContainsKey("url") ? secondToLast["url"] : secondToLast["path"];
|
||||
//普通分段才判断
|
||||
if (urlLast.StartsWith("http") && !Regex.IsMatch(urlLast, "\\$\\$Range=(\\d+)-(\\d+)"))
|
||||
{
|
||||
LOGGER.PrintLine(strings.checkingLast + (f["ContentType"] != "audio" ? "(Video)" : "(Audio)"));
|
||||
LOGGER.WriteLine(strings.checkingLast + (f["ContentType"] != "audio" ? "(Video)" : "(Audio)"));
|
||||
//倒数第二段正常,倒数第一段不正常
|
||||
if (checkValid(urlSecondToLast) && !checkValid(urlLast))
|
||||
fragments.RemoveAt(fragments.Count - 1);
|
||||
}
|
||||
}
|
||||
|
||||
//添加分段
|
||||
foreach (var seg in f["Fragments"])
|
||||
foreach (var seg in fragments)
|
||||
{
|
||||
var dur = seg.ContainsKey("duration") ? seg["duration"] : 0.0;
|
||||
var url = seg.ContainsKey("url") ? seg["url"] : seg["path"];
|
||||
sb.AppendLine($"#EXTINF:{dur.ToString("0.00")}");
|
||||
sb.AppendLine(url);
|
||||
if (Regex.IsMatch(url, "\\$\\$Range=(\\d+)-(\\d+)"))
|
||||
{
|
||||
var match = Regex.Match(url, "\\$\\$Range=(\\d+)-(\\d+)");
|
||||
string rangeStr = match.Value;
|
||||
long start = Convert.ToInt64(match.Groups[1].Value);
|
||||
long end = Convert.ToInt64(match.Groups[2].Value);
|
||||
sb.AppendLine($"#EXT-X-BYTERANGE:{end + 1 - start}@{start}");
|
||||
sb.AppendLine(url.Replace(rangeStr, ""));
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.AppendLine(url);
|
||||
}
|
||||
}
|
||||
|
||||
sb.AppendLine("#EXT-X-ENDLIST");
|
||||
@@ -663,7 +744,7 @@ namespace N_m3u8DL_CLI
|
||||
{
|
||||
var w = f["Width"];
|
||||
var h = f["Height"];
|
||||
if (w != -1 && h != -1)
|
||||
if (f["ContentType"] == "video")
|
||||
{
|
||||
if (f["Tbr"] > bandwidth && w > width)
|
||||
{
|
||||
@@ -684,9 +765,7 @@ namespace N_m3u8DL_CLI
|
||||
|
||||
foreach (var f in fs)
|
||||
{
|
||||
var w = f["Width"];
|
||||
var h = f["Height"];
|
||||
if (w == -1 && h == -1)
|
||||
if (f["ContentType"] == "audio")
|
||||
{
|
||||
if (f["Tbr"] > bandwidth)
|
||||
{
|
||||
@@ -731,6 +810,10 @@ namespace N_m3u8DL_CLI
|
||||
/// <returns></returns>
|
||||
static string CombineURL(string baseurl, string url)
|
||||
{
|
||||
if (url.StartsWith("$$Range"))
|
||||
{
|
||||
return baseurl + url;
|
||||
}
|
||||
Uri uri1 = new Uri(baseurl);
|
||||
Uri uri2 = new Uri(uri1, url);
|
||||
url = uri2.ToString();
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -178,6 +178,12 @@ namespace N_m3u8DL_CLI.NetCore
|
||||
{
|
||||
Global.NoProxy = true;
|
||||
}
|
||||
if (arguments.Has("--proxyAddress"))
|
||||
{
|
||||
var proxy = arguments.Get("--proxyAddress").Next.ToString();
|
||||
if (proxy.StartsWith("http://"))
|
||||
Global.UseProxyAddress = proxy;
|
||||
}
|
||||
if (arguments.Has("--headers"))
|
||||
{
|
||||
reqHeaders = arguments.Get("--headers").Next;
|
||||
|
@@ -305,4 +305,29 @@
|
||||
2020年12月12日
|
||||
- 修复MPD下同一个ID分散在不同Period导致下载不完全问题
|
||||
2020年12月20日
|
||||
- 支持解密虎课网
|
||||
- 支持解密虎课网
|
||||
2021年1月18日
|
||||
- 完善MPD下载相关
|
||||
- 重新打包多语言资源
|
||||
2021年1月24日
|
||||
- 适配Disney+资源
|
||||
- MPD选择流行为优化
|
||||
- 修复二进制合并时vtt字幕被合并为ts后缀问题
|
||||
2021年2月1日
|
||||
- 修正自定义KEY且存在IV时的隐患
|
||||
- 优化跳过PNG Header的算法
|
||||
2021年2月2日
|
||||
- 独播库自动加入referer
|
||||
- 修复气球云
|
||||
2021年2月10日
|
||||
- 修正MPD拼接BaseUrl逻辑
|
||||
2021年2月11日
|
||||
- 将CNTV视频修改为未加密链接
|
||||
2021年2月21日
|
||||
- MPD检测最后一个分片是否有效
|
||||
2021年2月22日
|
||||
- 添加用户网络代理支持,使用--proxyAddress指定代理地址。(@evanlabs)
|
||||
2021年3月3日
|
||||
- 修复M3U8选择音轨/字幕不生效问题
|
||||
- 外挂音轨时enableAudioOnly可仅下载音频
|
||||
- 移除气球云支持
|
22
N_m3u8DL-CLI/strings.Designer.cs
generated
22
N_m3u8DL-CLI/strings.Designer.cs
generated
@@ -47,8 +47,8 @@ namespace N_m3u8DL_CLI {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 重写当前线程的 CurrentUICulture 属性
|
||||
/// 重写当前线程的 CurrentUICulture 属性。
|
||||
/// 重写当前线程的 CurrentUICulture 属性,对
|
||||
/// 使用此强类型资源类的所有资源查找执行重写。
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Globalization.CultureInfo Culture {
|
||||
@@ -69,6 +69,15 @@ namespace N_m3u8DL_CLI {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 正在判断尾分片是否有效... 的本地化字符串。
|
||||
/// </summary>
|
||||
internal static string checkingLast {
|
||||
get {
|
||||
return ResourceManager.GetString("checkingLast", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 已关闭完整性检查 的本地化字符串。
|
||||
/// </summary>
|
||||
@@ -493,6 +502,15 @@ namespace N_m3u8DL_CLI {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 开始解析MPD内容... 的本地化字符串。
|
||||
/// </summary>
|
||||
internal static string startParsingMpd {
|
||||
get {
|
||||
return ResourceManager.GetString("startParsingMpd", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 重新解析m3u8... 的本地化字符串。
|
||||
/// </summary>
|
||||
|
@@ -201,6 +201,7 @@
|
||||
--downloadRange Range Set range for a video
|
||||
--stopSpeed Number Speed below this, retry(KB/s)
|
||||
--maxSpeed Number Set max download speed(KB/s)
|
||||
--proxyAddress http://xx Set HTTP 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 ffmpeg
|
||||
@@ -298,4 +299,10 @@
|
||||
<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>
|
||||
</root>
|
@@ -202,6 +202,7 @@
|
||||
--liveRecDur HH:MM:SS 直播录制时,达到此长度自动退出软件
|
||||
--stopSpeed Number 当速度低于此值时,重试(单位为KB/s)
|
||||
--maxSpeed Number 设置下载速度上限(单位为KB/s)
|
||||
--proxyAddress http://xx 设置HTTP代理, 如 http://127.0.0.1:8080
|
||||
--enableDelAfterDone 开启下载后删除临时文件夹的功能
|
||||
--enableMuxFastStart 开启混流mp4的FastStart特性
|
||||
--enableBinaryMerge 开启二进制合并分片
|
||||
@@ -299,4 +300,10 @@
|
||||
<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>
|
||||
</root>
|
@@ -202,6 +202,7 @@
|
||||
--liveRecDur HH:MM:SS 直播錄制時,達到此長度自動退出軟件
|
||||
--stopSpeed Number 當速度低於此值時,重試(單位為KB/s)
|
||||
--maxSpeed Number 設置下載速度上限(單位為KB/s)
|
||||
--proxyAddress http://xx 設置HTTP代理, 如 http://127.0.0.1:8080
|
||||
--enableDelAfterDone 開啟下載後刪除臨時文件夾的功能
|
||||
--enableMuxFastStart 開啟混流mp4的FastStart特性
|
||||
--enableBinaryMerge 開啟二進制合並分片
|
||||
@@ -299,4 +300,10 @@
|
||||
<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>
|
||||
</root>
|
@@ -18,9 +18,7 @@
|
||||
本项目已与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
|
||||
@@ -48,7 +46,7 @@
|
||||
|
||||
# 命令行选项
|
||||
```
|
||||
N_m3u8DL-CLI.exe <URL|JSON|FILE> [OPTIONS]
|
||||
N_m3u8DL-CLI.exe <URL|File|JSON> [OPTIONS]
|
||||
|
||||
--workDir Directory 设定程序工作目录
|
||||
--saveName Filename 设定存储文件名(不包括后缀)
|
||||
@@ -66,6 +64,7 @@ N_m3u8DL-CLI.exe <URL|JSON|FILE> [OPTIONS]
|
||||
--liveRecDur HH:MM:SS 直播录制时,达到此长度自动退出软件
|
||||
--stopSpeed Number 当速度低于此值时,重试(单位为KB/s)
|
||||
--maxSpeed Number 设置下载速度上限(单位为KB/s)
|
||||
--proxyAddress http://xx 设置HTTP代理, 如 http://127.0.0.1:8080
|
||||
--enableDelAfterDone 开启下载后删除临时文件夹的功能
|
||||
--enableMuxFastStart 开启混流mp4的FastStart特性
|
||||
--enableBinaryMerge 开启二进制合并分片
|
||||
@@ -81,4 +80,4 @@ N_m3u8DL-CLI.exe <URL|JSON|FILE> [OPTIONS]
|
||||
https://nilaoda.github.io/N_m3u8DL-CLI/
|
||||
|
||||
# 赞赏
|
||||
https://nilaoda.github.io/N_m3u8DL-CLI/source/images/alipay.png
|
||||

|
||||
|
@@ -47,6 +47,7 @@ N_m3u8DL-CLI.exe <URL|JSON|FILE> [OPTIONS]
|
||||
--downloadRange Range Set range for a video
|
||||
--stopSpeed Number Speed below this, retry(KB/s)
|
||||
--maxSpeed Number Set max download speed(KB/s)
|
||||
--proxyAddress http://xx Set HTTP 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 ffmpeg
|
||||
|
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
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
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
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user