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
38 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
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 |
@@ -11,25 +11,12 @@ namespace N_m3u8DL_CLI
|
|||||||
{
|
{
|
||||||
class DownloadManager
|
class DownloadManager
|
||||||
{
|
{
|
||||||
private static int calcTime = 1; //计算文件夹大小的间隔
|
|
||||||
private int stopCount = 0; //速度为零的停止
|
private int stopCount = 0; //速度为零的停止
|
||||||
private int timeOut = 10000; //超时设置
|
|
||||||
private static double downloadedSize = 0; //已下载大小
|
|
||||||
private static bool disableIntegrityCheck = false; //关闭完整性检查
|
|
||||||
|
|
||||||
private string jsonFile = string.Empty;
|
private string jsonFile = string.Empty;
|
||||||
private string headers = string.Empty;
|
|
||||||
private string downDir = string.Empty;
|
|
||||||
private string downName = string.Empty;
|
|
||||||
private string muxSetJson = string.Empty;
|
|
||||||
private int threads = 1;
|
|
||||||
private int retryCount = 5;
|
|
||||||
private static int count = 0;
|
|
||||||
private static int partsCount = 0;
|
|
||||||
private int total = 0;
|
private int total = 0;
|
||||||
public static string partsPadZero = string.Empty;
|
public static string partsPadZero = string.Empty;
|
||||||
string segsPadZero = string.Empty;
|
string segsPadZero = string.Empty;
|
||||||
bool delAfterDone = false;
|
|
||||||
private bool isVTT = false;
|
private bool isVTT = false;
|
||||||
bool externalAudio = false; //额外的音轨
|
bool externalAudio = false; //额外的音轨
|
||||||
string externalAudioUrl = "";
|
string externalAudioUrl = "";
|
||||||
@@ -37,28 +24,56 @@ namespace N_m3u8DL_CLI
|
|||||||
string externalSubUrl = "";
|
string externalSubUrl = "";
|
||||||
string fflogName = "_ffreport.log";
|
string fflogName = "_ffreport.log";
|
||||||
public static bool BinaryMerge = false;
|
public static bool BinaryMerge = false;
|
||||||
private bool noMerge = false;
|
|
||||||
private bool muxFastStart = true;
|
|
||||||
private string muxFormat = "mp4";
|
|
||||||
private static bool hasSetDir = false;
|
|
||||||
|
|
||||||
public int Threads { get => threads; set => threads = value; }
|
public int Threads { get; set; } = 1;
|
||||||
public int RetryCount { get => retryCount; set => retryCount = value; }
|
public int RetryCount { get; set; } = 5;
|
||||||
public string Headers { get => headers; set => headers = value; }
|
public string Headers { get; set; } = string.Empty;
|
||||||
public string DownDir { get => downDir; set => downDir = value; }
|
public string DownDir { get; set; } = string.Empty;
|
||||||
public string DownName { get => downName; set => downName = value; }
|
public string DownName { get; set; } = string.Empty;
|
||||||
public bool DelAfterDone { get => delAfterDone; set => delAfterDone = value; }
|
public bool DelAfterDone { get; set; } = false;
|
||||||
public string MuxFormat { get => muxFormat; set => muxFormat = value; }
|
public string MuxFormat { get; set; } = "mp4";
|
||||||
public bool MuxFastStart { get => muxFastStart; set => muxFastStart = value; }
|
public bool MuxFastStart { get; set; } = true;
|
||||||
public string MuxSetJson { get => muxSetJson; set => muxSetJson = value; }
|
public string MuxSetJson { get; set; } = string.Empty;
|
||||||
public int TimeOut { get => timeOut; set => timeOut = value; }
|
public int TimeOut { get; set; } = 10000; //超时设置
|
||||||
public static double DownloadedSize { get => downloadedSize; set => downloadedSize = value; }
|
public static double DownloadedSize { get; set; } = 0; //已下载大小
|
||||||
public static bool HasSetDir { get => hasSetDir; set => hasSetDir = value; }
|
public static bool HasSetDir { get; set; } = false;
|
||||||
public bool NoMerge { get => noMerge; set => noMerge = value; }
|
public bool NoMerge { get; set; } = false;
|
||||||
public static int CalcTime { get => calcTime; set => calcTime = value; }
|
public static int CalcTime { get; set; } = 1; //计算速度的间隔
|
||||||
public static int Count { get => count; set => count = value; }
|
public static int Count { get; set; } = 0;
|
||||||
public static int PartsCount { get => partsCount; set => partsCount = value; }
|
public static int PartsCount { get; set; } = 0;
|
||||||
public static bool DisableIntegrityCheck { get => disableIntegrityCheck; set => disableIntegrityCheck = value; }
|
public static bool DisableIntegrityCheck { get; set; } = false; //关闭完整性检查
|
||||||
|
|
||||||
|
static CancellationTokenSource cts = new CancellationTokenSource();
|
||||||
|
//计算下载速度
|
||||||
|
static System.Timers.Timer timer = new System.Timers.Timer(1000 * CalcTime); //实例化Timer类
|
||||||
|
|
||||||
|
public DownloadManager()
|
||||||
|
{
|
||||||
|
timer.AutoReset = true;
|
||||||
|
timer.Elapsed += delegate
|
||||||
|
{
|
||||||
|
Console.SetCursorPosition(0, 1);
|
||||||
|
Console.Write("Speed: " + Global.FormatFileSize((Global.BYTEDOWN) / CalcTime) + " / s".PadRight(70));
|
||||||
|
|
||||||
|
if (Global.HadReadInfo && Global.BYTEDOWN <= Global.STOP_SPEED * 1024 * CalcTime)
|
||||||
|
{
|
||||||
|
stopCount++;
|
||||||
|
Console.SetCursorPosition(0, 1);
|
||||||
|
Console.Write("Speed: " + Global.FormatFileSize((Global.BYTEDOWN) / CalcTime) + " / s [" + stopCount + "]".PadRight(70));
|
||||||
|
|
||||||
|
if (stopCount >= 12)
|
||||||
|
{
|
||||||
|
Global.ShouldStop = true;
|
||||||
|
cts.Cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
stopCount = 0;
|
||||||
|
Global.BYTEDOWN = 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
public void DoDownload()
|
public void DoDownload()
|
||||||
{
|
{
|
||||||
@@ -94,7 +109,6 @@ namespace N_m3u8DL_CLI
|
|||||||
PartsCount = parts.Count;
|
PartsCount = parts.Count;
|
||||||
segsPadZero = string.Empty.PadRight(oriCount.Length, '0');
|
segsPadZero = string.Empty.PadRight(oriCount.Length, '0');
|
||||||
partsPadZero = string.Empty.PadRight(Convert.ToString(parts.Count).Length, '0');
|
partsPadZero = string.Empty.PadRight(Convert.ToString(parts.Count).Length, '0');
|
||||||
CancellationTokenSource cts = new CancellationTokenSource();
|
|
||||||
|
|
||||||
//是直播视频
|
//是直播视频
|
||||||
if (isVOD == "False")
|
if (isVOD == "False")
|
||||||
@@ -104,7 +118,6 @@ namespace N_m3u8DL_CLI
|
|||||||
|
|
||||||
Global.ShouldStop = false; //是否该停止下载
|
Global.ShouldStop = false; //是否该停止下载
|
||||||
|
|
||||||
//监控文件夹变化
|
|
||||||
if (!Directory.Exists(DownDir))
|
if (!Directory.Exists(DownDir))
|
||||||
Directory.CreateDirectory(DownDir); //新建文件夹
|
Directory.CreateDirectory(DownDir); //新建文件夹
|
||||||
Watcher watcher = new Watcher(DownDir);
|
Watcher watcher = new Watcher(DownDir);
|
||||||
@@ -112,41 +125,9 @@ namespace N_m3u8DL_CLI
|
|||||||
watcher.PartsCount = PartsCount;
|
watcher.PartsCount = PartsCount;
|
||||||
watcher.WatcherStrat();
|
watcher.WatcherStrat();
|
||||||
|
|
||||||
//监控文件夹大小变化 via https://stackoverflow.com/questions/2869561/what-is-the-fastest-way-to-calculate-a-windows-folders-size/12665904#12665904
|
//开始计算速度
|
||||||
System.Timers.Timer timer = new System.Timers.Timer(1000 * CalcTime); //实例化Timer类
|
|
||||||
timer.AutoReset = true;
|
|
||||||
timer.Enabled = true;
|
timer.Enabled = true;
|
||||||
//Scripting.FileSystemObject fso = new Scripting.FileSystemObject();
|
cts = new CancellationTokenSource();
|
||||||
//Scripting.Folder folder = fso.GetFolder(DownDir);
|
|
||||||
timer.Elapsed += delegate
|
|
||||||
{
|
|
||||||
//采用COM组件获取文件夹的大小,需要引入 "Microsoft Scripting Runtime"
|
|
||||||
//double sizeInBytes = folder.Size;
|
|
||||||
Console.SetCursorPosition(0, 1);
|
|
||||||
//Console.WriteLine("Speed: " + Global.FormatFileSize((sizeInBytes - lastSizeInBytes) / calcTime) + " / s ");
|
|
||||||
Console.Write("Speed: " + Global.FormatFileSize((Global.BYTEDOWN) / CalcTime) + " / s".PadRight(70));
|
|
||||||
|
|
||||||
if (Global.HadReadInfo && Global.BYTEDOWN <= Global.STOP_SPEED * 1024 * CalcTime)
|
|
||||||
{
|
|
||||||
stopCount++;
|
|
||||||
Console.SetCursorPosition(0, 1);
|
|
||||||
Console.Write("Speed: " + Global.FormatFileSize((Global.BYTEDOWN) / CalcTime) + " / s [" + stopCount + "]".PadRight(70));
|
|
||||||
|
|
||||||
if (stopCount >= 12)
|
|
||||||
{
|
|
||||||
Global.ShouldStop = true;
|
|
||||||
cts.Cancel();
|
|
||||||
GC.Collect();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
stopCount = 0;
|
|
||||||
Global.BYTEDOWN = 0;
|
|
||||||
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
//开始调用下载
|
//开始调用下载
|
||||||
LOGGER.WriteLine(strings.startDownloading);
|
LOGGER.WriteLine(strings.startDownloading);
|
||||||
@@ -200,16 +181,10 @@ namespace N_m3u8DL_CLI
|
|||||||
sd.Key = firstSeg["key"].Value<string>();
|
sd.Key = firstSeg["key"].Value<string>();
|
||||||
sd.Iv = firstSeg["iv"].Value<string>();
|
sd.Iv = firstSeg["iv"].Value<string>();
|
||||||
}
|
}
|
||||||
try
|
if (firstSeg["expectByte"] != null)
|
||||||
{
|
|
||||||
sd.ExpectByte = firstSeg["expectByte"].Value<long>();
|
sd.ExpectByte = firstSeg["expectByte"].Value<long>();
|
||||||
}
|
if (firstSeg["startByte"] != null)
|
||||||
catch (Exception) { }
|
|
||||||
try
|
|
||||||
{
|
|
||||||
sd.StartByte = firstSeg["startByte"].Value<long>();
|
sd.StartByte = firstSeg["startByte"].Value<long>();
|
||||||
}
|
|
||||||
catch (Exception) { }
|
|
||||||
sd.Headers = Headers;
|
sd.Headers = Headers;
|
||||||
sd.SavePath = DownDir + "\\Part_" + 0.ToString(partsPadZero) + "\\" + firstSeg["index"].Value<int>().ToString(segsPadZero) + ".tsdownloading";
|
sd.SavePath = DownDir + "\\Part_" + 0.ToString(partsPadZero) + "\\" + firstSeg["index"].Value<int>().ToString(segsPadZero) + ".tsdownloading";
|
||||||
if (File.Exists(sd.SavePath))
|
if (File.Exists(sd.SavePath))
|
||||||
@@ -290,16 +265,10 @@ namespace N_m3u8DL_CLI
|
|||||||
sd.Key = info["key"].Value<string>();
|
sd.Key = info["key"].Value<string>();
|
||||||
sd.Iv = info["iv"].Value<string>();
|
sd.Iv = info["iv"].Value<string>();
|
||||||
}
|
}
|
||||||
try
|
if (firstSeg["expectByte"] != null)
|
||||||
{
|
|
||||||
sd.ExpectByte = info["expectByte"].Value<long>();
|
sd.ExpectByte = info["expectByte"].Value<long>();
|
||||||
}
|
if (firstSeg["startByte"] != null)
|
||||||
catch (Exception) { }
|
|
||||||
try
|
|
||||||
{
|
|
||||||
sd.StartByte = info["startByte"].Value<long>();
|
sd.StartByte = info["startByte"].Value<long>();
|
||||||
}
|
|
||||||
catch (Exception) { }
|
|
||||||
sd.Headers = Headers;
|
sd.Headers = Headers;
|
||||||
sd.SavePath = DownDir + "\\Part_" + info["part"].Value<int>().ToString(partsPadZero) + "\\" + info["index"].Value<int>().ToString(segsPadZero) + ".tsdownloading";
|
sd.SavePath = DownDir + "\\Part_" + info["part"].Value<int>().ToString(partsPadZero) + "\\" + info["index"].Value<int>().ToString(segsPadZero) + ".tsdownloading";
|
||||||
if (File.Exists(sd.SavePath))
|
if (File.Exists(sd.SavePath))
|
||||||
@@ -327,12 +296,8 @@ namespace N_m3u8DL_CLI
|
|||||||
|
|
||||||
watcher.WatcherStop();
|
watcher.WatcherStop();
|
||||||
|
|
||||||
//监控文件夹大小变化的收尾工作
|
//停止速度监测
|
||||||
timer.Enabled = false;
|
timer.Enabled = false;
|
||||||
timer.Close();
|
|
||||||
// cleanup COM
|
|
||||||
//System.Runtime.InteropServices.Marshal.ReleaseComObject(folder);
|
|
||||||
//System.Runtime.InteropServices.Marshal.ReleaseComObject(fso);
|
|
||||||
|
|
||||||
//检测是否下完
|
//检测是否下完
|
||||||
IsComplete(Convert.ToInt32(segCount));
|
IsComplete(Convert.ToInt32(segCount));
|
||||||
@@ -363,14 +328,13 @@ namespace N_m3u8DL_CLI
|
|||||||
Count++;
|
Count++;
|
||||||
LOGGER.WriteLine(strings.retryCount + Count + " / " + RetryCount);
|
LOGGER.WriteLine(strings.retryCount + Count + " / " + RetryCount);
|
||||||
LOGGER.PrintLine(strings.retryCount + Count + " / " + RetryCount, LOGGER.Warning);
|
LOGGER.PrintLine(strings.retryCount + Count + " / " + RetryCount, LOGGER.Warning);
|
||||||
Thread.Sleep(3000);
|
Thread.Sleep(6000);
|
||||||
GC.Collect(); //垃圾回收
|
|
||||||
DoDownload();
|
DoDownload();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else //开始合并
|
else //开始合并
|
||||||
{
|
{
|
||||||
LOGGER.PrintLine(strings.downloadComplete + (DisableIntegrityCheck ? "("+strings.disableIntegrityCheck+")" : ""));
|
LOGGER.PrintLine(strings.downloadComplete + (DisableIntegrityCheck ? "(" + strings.disableIntegrityCheck + ")" : ""));
|
||||||
Console.WriteLine();
|
Console.WriteLine();
|
||||||
if (NoMerge == false)
|
if (NoMerge == false)
|
||||||
{
|
{
|
||||||
@@ -539,7 +503,7 @@ namespace N_m3u8DL_CLI
|
|||||||
|
|
||||||
FFmpeg.OutPutPath = Path.Combine(Directory.GetParent(DownDir).FullName, DownName);
|
FFmpeg.OutPutPath = Path.Combine(Directory.GetParent(DownDir).FullName, DownName);
|
||||||
FFmpeg.ReportFile = driverName + "\\:" + exePath.Remove(0, exePath.IndexOf(':') + 1).Replace("\\", "/") + "/Logs/" + Path.GetFileNameWithoutExtension(LOGGER.LOGFILE) + fflogName;
|
FFmpeg.ReportFile = driverName + "\\:" + exePath.Remove(0, exePath.IndexOf(':') + 1).Replace("\\", "/") + "/Logs/" + Path.GetFileNameWithoutExtension(LOGGER.LOGFILE) + fflogName;
|
||||||
|
|
||||||
//合并分段
|
//合并分段
|
||||||
LOGGER.PrintLine(strings.startMerging);
|
LOGGER.PrintLine(strings.startMerging);
|
||||||
for (int i = 0; i < PartsCount; i++)
|
for (int i = 0; i < PartsCount; i++)
|
||||||
@@ -640,7 +604,7 @@ namespace N_m3u8DL_CLI
|
|||||||
parser.DownDir = Path.Combine(Path.GetDirectoryName(DownDir), parser.DownName);
|
parser.DownDir = Path.Combine(Path.GetDirectoryName(DownDir), parser.DownName);
|
||||||
LOGGER.WriteLine(strings.startParsing + externalAudioUrl);
|
LOGGER.WriteLine(strings.startParsing + externalAudioUrl);
|
||||||
LOGGER.WriteLine(strings.downloadingExternalAudioTrack);
|
LOGGER.WriteLine(strings.downloadingExternalAudioTrack);
|
||||||
DownName = DownName + "(Audio)";
|
DownName = parser.DownName;
|
||||||
fflogName = "_ffreport(Audio).log";
|
fflogName = "_ffreport(Audio).log";
|
||||||
DownDir = parser.DownDir;
|
DownDir = parser.DownDir;
|
||||||
parser.Parse(); //开始解析
|
parser.Parse(); //开始解析
|
||||||
|
@@ -30,8 +30,9 @@ namespace N_m3u8DL_CLI
|
|||||||
|
|
||||||
|
|
||||||
/*===============================================================================*/
|
/*===============================================================================*/
|
||||||
static string nowVer = "2.8.1";
|
static Version ver = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
|
||||||
static string nowDate = "20201121";
|
static string nowVer = $"{ver.Major}.{ver.Minor}.{ver.Build}";
|
||||||
|
static string nowDate = "20201202";
|
||||||
public static void WriteInit()
|
public static void WriteInit()
|
||||||
{
|
{
|
||||||
Console.Clear();
|
Console.Clear();
|
||||||
@@ -101,23 +102,25 @@ namespace N_m3u8DL_CLI
|
|||||||
public static string GetWebSource(String url, string headers = "", int TimeOut = 60000)
|
public static string GetWebSource(String url, string headers = "", int TimeOut = 60000)
|
||||||
{
|
{
|
||||||
string htmlCode = string.Empty;
|
string htmlCode = string.Empty;
|
||||||
for(int i = 0; i < 10; i++)
|
for (int i = 0; i < 10; i++)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
reProcess:
|
||||||
HttpWebRequest webRequest = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(url);
|
HttpWebRequest webRequest = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(url);
|
||||||
webRequest.Method = "GET";
|
webRequest.Method = "GET";
|
||||||
if (NoProxy) webRequest.Proxy = null;
|
if (NoProxy) webRequest.Proxy = null;
|
||||||
webRequest.UserAgent = "Mozilla/5.0 (Linux; U; Android 7.0; zh-cn; 15 Plus Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/66.0.3359.126 MQQBrowser/9.4 Mobile Safari/537.36";
|
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.Headers.Add("Accept-Encoding", "gzip, deflate");
|
webRequest.Accept = "*/*";
|
||||||
|
webRequest.Headers.Add("Accept-Encoding", "gzip, deflate, br");
|
||||||
webRequest.Timeout = TimeOut; //设置超时
|
webRequest.Timeout = TimeOut; //设置超时
|
||||||
webRequest.KeepAlive = false;
|
webRequest.KeepAlive = false;
|
||||||
webRequest.AllowAutoRedirect = true; //自动跳转
|
webRequest.AllowAutoRedirect = false; //手动处理重定向,否则会丢失Referer
|
||||||
if (url.Contains("pcvideo") && url.Contains(".titan.mgtv.com"))
|
if (url.Contains("pcvideo") && url.Contains(".titan.mgtv.com"))
|
||||||
{
|
{
|
||||||
webRequest.UserAgent = "";
|
webRequest.UserAgent = "";
|
||||||
if (!url.Contains("/internettv/"))
|
if (!url.Contains("/internettv/"))
|
||||||
webRequest.Referer = "https://player.mgtv.com/mgtv_v6_player/PlayerCore.swf";
|
webRequest.Referer = "https://www.mgtv.com";
|
||||||
webRequest.Headers.Add("Cookie", "MQGUID");
|
webRequest.Headers.Add("Cookie", "MQGUID");
|
||||||
}
|
}
|
||||||
//添加headers
|
//添加headers
|
||||||
@@ -146,8 +149,16 @@ namespace N_m3u8DL_CLI
|
|||||||
}
|
}
|
||||||
HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse();
|
HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse();
|
||||||
|
|
||||||
|
//302
|
||||||
|
if (webResponse.Headers.Get("Location") != null)
|
||||||
|
{
|
||||||
|
url = webResponse.Headers.Get("Location");
|
||||||
|
webResponse.Close();
|
||||||
|
goto reProcess;
|
||||||
|
}
|
||||||
|
|
||||||
//文件过大则认为不是m3u8
|
//文件过大则认为不是m3u8
|
||||||
if (webResponse.ContentLength != -1 && webRequest.ContentLength > 50 * 1024 * 1024) return "";
|
if (webResponse.ContentLength != -1 && webResponse.ContentLength > 50 * 1024 * 1024) return "";
|
||||||
|
|
||||||
if (webResponse.ContentEncoding != null
|
if (webResponse.ContentEncoding != null
|
||||||
&& webResponse.ContentEncoding.ToLower() == "gzip") //如果使用了GZip则先解压
|
&& webResponse.ContentEncoding.ToLower() == "gzip") //如果使用了GZip则先解压
|
||||||
@@ -406,14 +417,17 @@ namespace N_m3u8DL_CLI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
reProcess:
|
||||||
byte[] arraryByte;
|
byte[] arraryByte;
|
||||||
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
|
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
|
||||||
req.Method = "GET";
|
req.Method = "GET";
|
||||||
req.Timeout = timeOut;
|
req.Timeout = timeOut;
|
||||||
req.ReadWriteTimeout = timeOut; //重要
|
req.ReadWriteTimeout = timeOut; //重要
|
||||||
|
req.AllowAutoRedirect = false; //手动处理重定向,否则会丢失Referer
|
||||||
if (NoProxy) req.Proxy = null;
|
if (NoProxy) req.Proxy = null;
|
||||||
req.Headers.Add("Accept-Encoding", "gzip, deflate");
|
req.Headers.Add("Accept-Encoding", "gzip, deflate");
|
||||||
req.Accept = "*/*";
|
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";
|
||||||
//添加headers
|
//添加headers
|
||||||
if (headers != "")
|
if (headers != "")
|
||||||
{
|
{
|
||||||
@@ -441,6 +455,13 @@ namespace N_m3u8DL_CLI
|
|||||||
|
|
||||||
using (HttpWebResponse wr = (HttpWebResponse)req.GetResponse())
|
using (HttpWebResponse wr = (HttpWebResponse)req.GetResponse())
|
||||||
{
|
{
|
||||||
|
//302
|
||||||
|
if (wr.Headers.Get("Location") != null)
|
||||||
|
{
|
||||||
|
url = wr.Headers.Get("Location");
|
||||||
|
wr.Close();
|
||||||
|
goto reProcess;
|
||||||
|
}
|
||||||
if (wr.ContentEncoding != null && wr.ContentEncoding.ToLower() == "gzip") //如果使用了GZip则先解压
|
if (wr.ContentEncoding != null && wr.ContentEncoding.ToLower() == "gzip") //如果使用了GZip则先解压
|
||||||
{
|
{
|
||||||
using (Stream streamReceive = wr.GetResponseStream())
|
using (Stream streamReceive = wr.GetResponseStream())
|
||||||
@@ -501,10 +522,11 @@ namespace N_m3u8DL_CLI
|
|||||||
if (shouldStop)
|
if (shouldStop)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
reProcess:
|
||||||
HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
|
HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
|
||||||
request.Timeout = timeOut;
|
request.Timeout = timeOut;
|
||||||
request.ReadWriteTimeout = timeOut; //重要
|
request.ReadWriteTimeout = timeOut; //重要
|
||||||
request.AllowAutoRedirect = true;
|
request.AllowAutoRedirect = false; //手动处理重定向,否则会丢失Referer
|
||||||
request.KeepAlive = false;
|
request.KeepAlive = false;
|
||||||
request.Method = "GET";
|
request.Method = "GET";
|
||||||
if (NoProxy) request.Proxy = null;
|
if (NoProxy) request.Proxy = null;
|
||||||
@@ -514,11 +536,11 @@ namespace N_m3u8DL_CLI
|
|||||||
{
|
{
|
||||||
request.UserAgent = "";
|
request.UserAgent = "";
|
||||||
if (!url.Contains("/internettv/"))
|
if (!url.Contains("/internettv/"))
|
||||||
request.Referer = "https://player.mgtv.com/mgtv_v6_player/PlayerCore.swf";
|
request.Referer = "https://www.mgtv.com";
|
||||||
request.Headers.Add("Cookie", "MQGUID");
|
request.Headers.Add("Cookie", "MQGUID");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
request.UserAgent = "Mozilla/5.0 (Linux; U; Android 7.0; zh-cn; 15 Plus Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/66.0.3359.126 MQQBrowser/9.4 Mobile Safari/537.36";
|
request.UserAgent = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36";
|
||||||
//下载部分字节
|
//下载部分字节
|
||||||
if (expectByte != -1)
|
if (expectByte != -1)
|
||||||
request.AddRange("bytes", startByte, startByte + expectByte - 1);
|
request.AddRange("bytes", startByte, startByte + expectByte - 1);
|
||||||
@@ -552,6 +574,13 @@ namespace N_m3u8DL_CLI
|
|||||||
bool pngHeader = false; //PNG HEADER检测
|
bool pngHeader = false; //PNG HEADER检测
|
||||||
using (var response = (HttpWebResponse)request.GetResponse())
|
using (var response = (HttpWebResponse)request.GetResponse())
|
||||||
{
|
{
|
||||||
|
//302
|
||||||
|
if (response.Headers.Get("Location") != null)
|
||||||
|
{
|
||||||
|
url = response.Headers.Get("Location");
|
||||||
|
response.Close();
|
||||||
|
goto reProcess;
|
||||||
|
}
|
||||||
using (var responseStream = response.GetResponseStream())
|
using (var responseStream = response.GetResponseStream())
|
||||||
{
|
{
|
||||||
using (var stream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Write))
|
using (var stream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Write))
|
||||||
@@ -560,7 +589,7 @@ namespace N_m3u8DL_CLI
|
|||||||
totalLen = response.ContentLength;
|
totalLen = response.ContentLength;
|
||||||
byte[] bArr = new byte[1024];
|
byte[] bArr = new byte[1024];
|
||||||
int size = responseStream.Read(bArr, 0, (int)bArr.Length);
|
int size = responseStream.Read(bArr, 0, (int)bArr.Length);
|
||||||
if (!pngHeader && size > 3 && 137 == bArr[0] && 80 == bArr[1] && 78 == bArr[2] && 71 == bArr[3])
|
if (!pngHeader && size > 3 && 137 == bArr[0] && 80 == bArr[1] && 78 == bArr[2] && 71 == bArr[3])
|
||||||
{
|
{
|
||||||
pngHeader = true;
|
pngHeader = true;
|
||||||
}
|
}
|
||||||
@@ -593,10 +622,11 @@ namespace N_m3u8DL_CLI
|
|||||||
}
|
}
|
||||||
if (shouldStop)
|
if (shouldStop)
|
||||||
try { File.Delete(path); } catch (Exception) { }
|
try { File.Delete(path); } catch (Exception) { }
|
||||||
if (totalLen != -1 && downLen != totalLen)
|
if (totalLen != -1 && downLen != totalLen)
|
||||||
try { File.Delete(path); } catch (Exception) { }
|
try { File.Delete(path); } catch (Exception) { }
|
||||||
if (pngHeader)
|
if (pngHeader)
|
||||||
TrySkipPngHeader(path);
|
TrySkipPngHeader(path);
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<Import Project="..\packages\Costura.Fody.4.1.0\build\Costura.Fody.props" Condition="Exists('..\packages\Costura.Fody.4.1.0\build\Costura.Fody.props')" />
|
||||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
@@ -12,6 +13,8 @@
|
|||||||
<FileAlignment>512</FileAlignment>
|
<FileAlignment>512</FileAlignment>
|
||||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||||
<TargetFrameworkProfile />
|
<TargetFrameworkProfile />
|
||||||
|
<NuGetPackageImportStamp>
|
||||||
|
</NuGetPackageImportStamp>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
<PlatformTarget>x86</PlatformTarget>
|
<PlatformTarget>x86</PlatformTarget>
|
||||||
@@ -38,6 +41,9 @@
|
|||||||
<ApplicationIcon>logo_3Iv_icon.ico</ApplicationIcon>
|
<ApplicationIcon>logo_3Iv_icon.ico</ApplicationIcon>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Reference Include="Costura, Version=4.1.0.0, Culture=neutral, PublicKeyToken=9919ef960d84173d, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\Costura.Fody.4.1.0\lib\net40\Costura.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
<Reference Include="Microsoft.JScript" />
|
<Reference Include="Microsoft.JScript" />
|
||||||
<Reference Include="netstandard, Version=2.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51" />
|
<Reference Include="netstandard, Version=2.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51" />
|
||||||
<Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
<Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||||
@@ -130,4 +136,12 @@
|
|||||||
</EmbeddedResource>
|
</EmbeddedResource>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
|
<Import Project="..\packages\Fody.6.0.0\build\Fody.targets" Condition="Exists('..\packages\Fody.6.0.0\build\Fody.targets')" />
|
||||||
|
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||||
|
<PropertyGroup>
|
||||||
|
<ErrorText>这台计算机上缺少此项目引用的 NuGet 程序包。使用“NuGet 程序包还原”可下载这些程序包。有关更多信息,请参见 http://go.microsoft.com/fwlink/?LinkID=322105。缺少的文件是 {0}。</ErrorText>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Error Condition="!Exists('..\packages\Fody.6.0.0\build\Fody.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Fody.6.0.0\build\Fody.targets'))" />
|
||||||
|
<Error Condition="!Exists('..\packages\Costura.Fody.4.1.0\build\Costura.Fody.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Costura.Fody.4.1.0\build\Costura.Fody.props'))" />
|
||||||
|
</Target>
|
||||||
</Project>
|
</Project>
|
||||||
|
@@ -118,14 +118,14 @@ namespace N_m3u8DL_CLI
|
|||||||
m3u8Content = DecodeImooc.DecodeM3u8(m3u8Content);
|
m3u8Content = DecodeImooc.DecodeM3u8(m3u8Content);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m3u8Content.Trim().StartsWith("<?xml version") && m3u8Content.Contains("<MPD"))
|
if (m3u8Content.Contains("</MPD>") && m3u8Content.Contains("<MPD"))
|
||||||
{
|
{
|
||||||
var mpdSavePath = Path.Combine(DownDir, "dash.mpd");
|
var mpdSavePath = Path.Combine(DownDir, "dash.mpd");
|
||||||
//输出mpd文件
|
//输出mpd文件
|
||||||
File.WriteAllText(mpdSavePath, m3u8Content);
|
File.WriteAllText(mpdSavePath, m3u8Content);
|
||||||
//分析mpd文件
|
//分析mpd文件
|
||||||
M3u8Url = Global.Get302(M3u8Url, Headers);
|
M3u8Url = Global.Get302(M3u8Url, Headers);
|
||||||
var newUri = MPDParser.Parse(DownDir, M3u8Url, m3u8Content);
|
var newUri = MPDParser.Parse(DownDir, M3u8Url, m3u8Content, BaseUrl);
|
||||||
M3u8Url = newUri;
|
M3u8Url = newUri;
|
||||||
m3u8Content = File.ReadAllText(new Uri(M3u8Url).LocalPath);
|
m3u8Content = File.ReadAllText(new Uri(M3u8Url).LocalPath);
|
||||||
}
|
}
|
||||||
@@ -332,7 +332,7 @@ namespace N_m3u8DL_CLI
|
|||||||
else if (line.StartsWith(HLSTags.ext_x_i_frame_stream_inf)) ;
|
else if (line.StartsWith(HLSTags.ext_x_i_frame_stream_inf)) ;
|
||||||
else if (line.StartsWith(HLSTags.ext_x_media))
|
else if (line.StartsWith(HLSTags.ext_x_media))
|
||||||
{
|
{
|
||||||
if (Global.GetTagAttribute(line, "TYPE") == "AUDIO")
|
if (Global.GetTagAttribute(line, "TYPE") == "AUDIO" && !MEDIA_AUDIO.ContainsKey(Global.GetTagAttribute(line, "GROUP-ID")))
|
||||||
MEDIA_AUDIO.Add(Global.GetTagAttribute(line, "GROUP-ID"), CombineURL(BaseUrl, Global.GetTagAttribute(line, "URI")));
|
MEDIA_AUDIO.Add(Global.GetTagAttribute(line, "GROUP-ID"), CombineURL(BaseUrl, Global.GetTagAttribute(line, "URI")));
|
||||||
if (Global.GetTagAttribute(line, "TYPE") == "SUBTITLES")
|
if (Global.GetTagAttribute(line, "TYPE") == "SUBTITLES")
|
||||||
{
|
{
|
||||||
@@ -864,9 +864,7 @@ namespace N_m3u8DL_CLI
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static string GetBaseUrl(string m3u8url, string headers)
|
public static string GetBaseUrl(string m3u8url, string headers)
|
||||||
{
|
{
|
||||||
if (!isQiQiuYun && Global.Get302(m3u8url, headers) != m3u8url)
|
string url = Global.Get302(m3u8url, headers);
|
||||||
m3u8url = Global.Get302(m3u8url, headers);
|
|
||||||
string url = Global.Get302(m3u8url);
|
|
||||||
if (url.Contains("?"))
|
if (url.Contains("?"))
|
||||||
url = url.Remove(url.LastIndexOf('?'));
|
url = url.Remove(url.LastIndexOf('?'));
|
||||||
url = url.Substring(0, url.LastIndexOf('/') + 1);
|
url = url.Substring(0, url.LastIndexOf('/') + 1);
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -284,4 +284,19 @@
|
|||||||
2020年11月20日
|
2020年11月20日
|
||||||
- 识别大部分mpd地址,自动转换为m3u8并下载
|
- 识别大部分mpd地址,自动转换为m3u8并下载
|
||||||
- GIF HEADER检测
|
- GIF HEADER检测
|
||||||
- 修复BUG
|
- 修复BUG
|
||||||
|
2020年11月22日
|
||||||
|
- 解决HTTPS协议自动重定向后,Referer丢失问题
|
||||||
|
- 新的任务速度监控逻辑
|
||||||
|
2020年11月23日
|
||||||
|
- 将默认UA修改为 Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36
|
||||||
|
- 修改芒果TV请求头
|
||||||
|
2020年11月25日
|
||||||
|
- 修正MPD判断最高清晰度的逻辑
|
||||||
|
- 在MPD输入下支持选择音轨
|
||||||
|
- 修复BUG
|
||||||
|
2020年11月26日
|
||||||
|
- 优化MPD识别方案
|
||||||
|
- 修复MPD情况下时间戳溢出问题
|
||||||
|
2020年12月2日
|
||||||
|
- FIX Language Bug
|
@@ -1,5 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<packages>
|
<packages>
|
||||||
|
<package id="Fody" version="6.0.0" targetFramework="net46" developmentDependency="true" />
|
||||||
|
<package id="Costura.Fody" version="4.1.0" targetFramework="net46" />
|
||||||
<package id="Newtonsoft.Json" version="12.0.3" targetFramework="net46" />
|
<package id="Newtonsoft.Json" version="12.0.3" targetFramework="net46" />
|
||||||
<package id="NiL.JS" version="2.5.1428" targetFramework="net46" />
|
<package id="NiL.JS" version="2.5.1428" targetFramework="net46" />
|
||||||
</packages>
|
</packages>
|
Reference in New Issue
Block a user