合并252 pull request

croire 3 years ago
parent 9fda62b962
commit 6f21977c8f

@ -1,4 +1,4 @@
using DownKyi.Core.BiliApi.VideoStream; using DownKyi.Core.BiliApi.VideoStream;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@ -11,6 +11,7 @@ namespace DownKyi.Models
{ {
// 初始化下载的文件列表 // 初始化下载的文件列表
DownloadFiles = new Dictionary<string, string>(); DownloadFiles = new Dictionary<string, string>();
DownloadedFiles = new List<string>();
} }
// Aria相关 // Aria相关
@ -19,6 +20,9 @@ namespace DownKyi.Models
// 下载的文件 // 下载的文件
public Dictionary<string, string> DownloadFiles { get; set; } public Dictionary<string, string> DownloadFiles { get; set; }
// 已下载的文件
public List<string> DownloadedFiles { get; set; }
// 视频类别 // 视频类别
public PlayStreamType PlayStreamType { get; set; } public PlayStreamType PlayStreamType { get; set; }

@ -1,4 +1,4 @@
using DownKyi.Core.Aria2cNet; using DownKyi.Core.Aria2cNet;
using DownKyi.Core.Aria2cNet.Client; using DownKyi.Core.Aria2cNet.Client;
using DownKyi.Core.Aria2cNet.Client.Entity; using DownKyi.Core.Aria2cNet.Client.Entity;
using DownKyi.Core.Aria2cNet.Server; using DownKyi.Core.Aria2cNet.Server;
@ -141,6 +141,11 @@ namespace DownKyi.Services.Download
string fileName = Guid.NewGuid().ToString("N"); string fileName = Guid.NewGuid().ToString("N");
string key = $"{downloadVideo.Id}_{downloadVideo.Codecs}"; string key = $"{downloadVideo.Id}_{downloadVideo.Codecs}";
// 老版本数据库没有这一项会变成null
if (downloading.Downloading.DownloadedFiles == null)
downloading.Downloading.DownloadedFiles = new List<string>();
if (downloading.Downloading.DownloadedFiles.Contains(key))
return Path.Combine(path, fileName);
if (downloading.Downloading.DownloadFiles.ContainsKey(key)) if (downloading.Downloading.DownloadFiles.ContainsKey(key))
{ {
// 如果存在,表示下载过, // 如果存在,表示下载过,
@ -155,6 +160,9 @@ namespace DownKyi.Services.Download
downloading.Downloading.DownloadFiles.Add(key, fileName); downloading.Downloading.DownloadFiles.Add(key, fileName);
} }
catch (ArgumentException) { } catch (ArgumentException) { }
// Gid最好能是每个文件单独存储现在复用有可能会混
// 不过好消息是下载是按固定顺序的,而且下载了两个音频会混流不过
downloading.Downloading.Gid = null;
} }
// 开始下载 // 开始下载
@ -162,6 +170,7 @@ namespace DownKyi.Services.Download
switch (downloadStatus) switch (downloadStatus)
{ {
case DownloadResult.SUCCESS: case DownloadResult.SUCCESS:
downloading.Downloading.DownloadedFiles.Add(key);
return Path.Combine(path, fileName); return Path.Combine(path, fileName);
case DownloadResult.FAILED: case DownloadResult.FAILED:
case DownloadResult.ABORT: case DownloadResult.ABORT:
@ -544,256 +553,258 @@ namespace DownKyi.Services.Download
Directory.CreateDirectory(path); Directory.CreateDirectory(path);
} }
await Task.Run(new Action(() => try
{ {
// 初始化 await Task.Run(new Action(() =>
downloading.DownloadStatusTitle = string.Empty;
downloading.DownloadContent = string.Empty;
//downloading.Downloading.DownloadFiles.Clear();
// 解析并依次下载音频、视频、弹幕、字幕、封面等内容
Parse(downloading);
// 设置下载状态
// 必须在解析之后设置为DOWNLOADING
downloading.Downloading.DownloadStatus = DownloadStatus.DOWNLOADING;
// 暂停
Pause(downloading);
// 是否存在
var isExist = IsExist(downloading);
if (!isExist.Result)
{ {
return; // 初始化
} downloading.DownloadStatusTitle = string.Empty;
downloading.DownloadContent = string.Empty;
//downloading.Downloading.DownloadFiles.Clear();
// 解析并依次下载音频、视频、弹幕、字幕、封面等内容
Parse(downloading);
// 暂停
Pause(downloading);
// 是否存在
var isExist = IsExist(downloading);
if (!isExist.Result)
{
return;
}
string audioUid = null; string audioUid = null;
// 如果需要下载音频 // 如果需要下载音频
if (downloading.DownloadBase.NeedDownloadContent["downloadAudio"]) if (downloading.DownloadBase.NeedDownloadContent["downloadAudio"])
{
//audioUid = DownloadAudio(downloading);
for (int i = 0; i < retry; i++)
{ {
audioUid = DownloadAudio(downloading); //audioUid = DownloadAudio(downloading);
if (audioUid != null && audioUid != "<null>") for (int i = 0; i < retry; i++)
{ {
break; audioUid = DownloadAudio(downloading);
if (audioUid != null && audioUid != "<null>")
{
break;
}
} }
} }
} if (audioUid == "<null>")
if (audioUid == "<null>") {
{ DownloadFailed(downloading);
DownloadFailed(downloading); return;
return; }
}
// 暂停 // 暂停
Pause(downloading); Pause(downloading);
// 是否存在 // 是否存在
isExist = IsExist(downloading); isExist = IsExist(downloading);
if (!isExist.Result) if (!isExist.Result)
{ {
return; return;
} }
string videoUid = null; string videoUid = null;
// 如果需要下载视频 // 如果需要下载视频
if (downloading.DownloadBase.NeedDownloadContent["downloadVideo"]) if (downloading.DownloadBase.NeedDownloadContent["downloadVideo"])
{
//videoUid = DownloadVideo(downloading);
for (int i = 0; i < retry; i++)
{ {
videoUid = DownloadVideo(downloading); //videoUid = DownloadVideo(downloading);
if (videoUid != null && videoUid != "<null>") for (int i = 0; i < retry; i++)
{ {
break; videoUid = DownloadVideo(downloading);
if (videoUid != null && videoUid != "<null>")
{
break;
}
} }
} }
} if (videoUid == "<null>")
if (videoUid == "<null>") {
{ DownloadFailed(downloading);
DownloadFailed(downloading); return;
return; }
}
// 暂停
Pause(downloading);
// 是否存在
isExist = IsExist(downloading);
if (!isExist.Result)
{
return;
}
string outputDanmaku = null;
// 如果需要下载弹幕
if (downloading.DownloadBase.NeedDownloadContent["downloadDanmaku"])
{
outputDanmaku = DownloadDanmaku(downloading);
}
// 暂停
Pause(downloading);
// 是否存在
isExist = IsExist(downloading);
if (!isExist.Result)
{
return;
}
List<string> outputSubtitles = null; // 暂停
// 如果需要下载字幕 Pause(downloading);
if (downloading.DownloadBase.NeedDownloadContent["downloadSubtitle"]) // 是否存在
{ isExist = IsExist(downloading);
outputSubtitles = DownloadSubtitle(downloading); if (!isExist.Result)
} {
return;
}
// 暂停 string outputDanmaku = null;
Pause(downloading); // 如果需要下载弹幕
// 是否存在 if (downloading.DownloadBase.NeedDownloadContent["downloadDanmaku"])
isExist = IsExist(downloading); {
if (!isExist.Result) outputDanmaku = DownloadDanmaku(downloading);
{ }
return;
}
string outputCover = null; // 暂停
string outputPageCover = null; Pause(downloading);
// 如果需要下载封面 // 是否存在
if (downloading.DownloadBase.NeedDownloadContent["downloadCover"]) isExist = IsExist(downloading);
{ if (!isExist.Result)
string fileName = $"{downloading.DownloadBase.FilePath}.{GetImageExtension(downloading.DownloadBase.PageCoverUrl)}"; {
return;
}
// page的封面 List<string> outputSubtitles = null;
outputPageCover = DownloadCover(downloading, downloading.DownloadBase.PageCoverUrl, fileName); // 如果需要下载字幕
// 封面 if (downloading.DownloadBase.NeedDownloadContent["downloadSubtitle"])
outputCover = DownloadCover(downloading, downloading.DownloadBase.CoverUrl, $"{path}/Cover.{GetImageExtension(downloading.DownloadBase.CoverUrl)}"); {
} outputSubtitles = DownloadSubtitle(downloading);
}
// 暂停 // 暂停
Pause(downloading); Pause(downloading);
// 是否存在 // 是否存在
isExist = IsExist(downloading); isExist = IsExist(downloading);
if (!isExist.Result) if (!isExist.Result)
{ {
return; return;
} }
// 混流 string outputCover = null;
string outputMedia = string.Empty; string outputPageCover = null;
if (downloading.DownloadBase.NeedDownloadContent["downloadAudio"] || downloading.DownloadBase.NeedDownloadContent["downloadVideo"]) // 如果需要下载封面
{ if (downloading.DownloadBase.NeedDownloadContent["downloadCover"])
outputMedia = MixedFlow(downloading, audioUid, videoUid); {
} string fileName = $"{downloading.DownloadBase.FilePath}.{GetImageExtension(downloading.DownloadBase.PageCoverUrl)}";
// 暂停 // page的封面
//Pause(downloading); outputPageCover = DownloadCover(downloading, downloading.DownloadBase.PageCoverUrl, fileName);
// 是否存在 // 封面
isExist = IsExist(downloading); outputCover = DownloadCover(downloading, downloading.DownloadBase.CoverUrl, $"{path}/Cover.{GetImageExtension(downloading.DownloadBase.CoverUrl)}");
if (!isExist.Result) }
{
return;
}
// 检测音频、视频是否下载成功 // 暂停
bool isMediaSuccess = true; Pause(downloading);
if (downloading.DownloadBase.NeedDownloadContent["downloadAudio"] || downloading.DownloadBase.NeedDownloadContent["downloadVideo"]) // 是否存在
{ isExist = IsExist(downloading);
// 只有下载音频不下载视频时才输出aac if (!isExist.Result)
// 只要下载视频就输出mp4
if (File.Exists(outputMedia))
{ {
// 成功 return;
isMediaSuccess = true;
} }
else
// 混流
string outputMedia = string.Empty;
if (downloading.DownloadBase.NeedDownloadContent["downloadAudio"] || downloading.DownloadBase.NeedDownloadContent["downloadVideo"])
{ {
isMediaSuccess = false; outputMedia = MixedFlow(downloading, audioUid, videoUid);
} }
}
// 检测弹幕是否下载成功 // 暂停
bool isDanmakuSuccess = true; //Pause(downloading);
if (downloading.DownloadBase.NeedDownloadContent["downloadDanmaku"]) // 是否存在
{ isExist = IsExist(downloading);
if (File.Exists(outputDanmaku)) if (!isExist.Result)
{ {
// 成功 return;
isDanmakuSuccess = true;
} }
else
// 检测音频、视频是否下载成功
bool isMediaSuccess = true;
if (downloading.DownloadBase.NeedDownloadContent["downloadAudio"] || downloading.DownloadBase.NeedDownloadContent["downloadVideo"])
{ {
isDanmakuSuccess = false; // 只有下载音频不下载视频时才输出aac
// 只要下载视频就输出mp4
if (File.Exists(outputMedia))
{
// 成功
isMediaSuccess = true;
}
else
{
isMediaSuccess = false;
}
} }
}
// 检测字幕是否下载成功 // 检测弹幕是否下载成功
bool isSubtitleSuccess = true; bool isDanmakuSuccess = true;
if (downloading.DownloadBase.NeedDownloadContent["downloadSubtitle"]) if (downloading.DownloadBase.NeedDownloadContent["downloadDanmaku"])
{
if (outputSubtitles == null)
{ {
// 为null时表示不存在字幕 if (File.Exists(outputDanmaku))
{
// 成功
isDanmakuSuccess = true;
}
else
{
isDanmakuSuccess = false;
}
} }
else
// 检测字幕是否下载成功
bool isSubtitleSuccess = true;
if (downloading.DownloadBase.NeedDownloadContent["downloadSubtitle"])
{ {
foreach (string subtitle in outputSubtitles) if (outputSubtitles == null)
{
// 为null时表示不存在字幕
}
else
{ {
if (!File.Exists(subtitle)) foreach (string subtitle in outputSubtitles)
{ {
// 如果有一个不存在则失败 if (!File.Exists(subtitle))
isSubtitleSuccess = false; {
// 如果有一个不存在则失败
isSubtitleSuccess = false;
}
} }
} }
} }
}
// 检测封面是否下载成功 // 检测封面是否下载成功
bool isCover = true; bool isCover = true;
if (downloading.DownloadBase.NeedDownloadContent["downloadCover"]) if (downloading.DownloadBase.NeedDownloadContent["downloadCover"])
{
if (File.Exists(outputCover) || File.Exists(outputPageCover))
{ {
// 成功 if (File.Exists(outputCover) || File.Exists(outputPageCover))
isCover = true; {
// 成功
isCover = true;
}
else
{
isCover = false;
}
} }
else
if (!isMediaSuccess || !isDanmakuSuccess || !isSubtitleSuccess || !isCover)
{ {
isCover = false; DownloadFailed(downloading);
return;
} }
}
if (!isMediaSuccess || !isDanmakuSuccess || !isSubtitleSuccess || !isCover)
{
DownloadFailed(downloading);
return;
}
// 下载完成后处理
Downloaded downloaded = new Downloaded
{
MaxSpeedDisplay = Format.FormatSpeed(downloading.Downloading.MaxSpeed),
};
// 设置完成时间
downloaded.SetFinishedTimestamp(new DateTimeOffset(DateTime.UtcNow).ToUnixTimeSeconds());
DownloadedItem downloadedItem = new DownloadedItem // 下载完成后处理
{ Downloaded downloaded = new Downloaded
DownloadBase = downloading.DownloadBase, {
Downloaded = downloaded MaxSpeedDisplay = Format.FormatSpeed(downloading.Downloading.MaxSpeed),
}; };
// 设置完成时间
downloaded.SetFinishedTimestamp(new DateTimeOffset(DateTime.UtcNow).ToUnixTimeSeconds());
App.PropertyChangeAsync(new Action(() => DownloadedItem downloadedItem = new DownloadedItem
{ {
// 加入到下载完成list中并从下载中list去除 DownloadBase = downloading.DownloadBase,
downloadedList.Add(downloadedItem); Downloaded = downloaded
downloadingList.Remove(downloading); };
// 下载完成列表排序 App.PropertyChangeAsync(new Action(() =>
DownloadFinishedSort finishedSort = SettingsManager.GetInstance().GetDownloadFinishedSort(); {
App.SortDownloadedList(finishedSort); // 加入到下载完成list中并从下载中list去除
downloadedList.Add(downloadedItem);
downloadingList.Remove(downloading);
// 下载完成列表排序
DownloadFinishedSort finishedSort = SettingsManager.GetInstance().GetDownloadFinishedSort();
App.SortDownloadedList(finishedSort);
}));
})); }));
})); }
catch (OperationCanceledException)
{
}
} }
/// <summary> /// <summary>
@ -836,33 +847,11 @@ namespace DownKyi.Services.Download
/// <param name="downloading"></param> /// <param name="downloading"></param>
private void Pause(DownloadingItem downloading) private void Pause(DownloadingItem downloading)
{ {
string oldStatus = downloading.DownloadStatusTitle;
downloading.DownloadStatusTitle = DictionaryResource.GetString("Pausing"); downloading.DownloadStatusTitle = DictionaryResource.GetString("Pausing");
while (downloading.Downloading.DownloadStatus == DownloadStatus.PAUSE) if (downloading.Downloading.DownloadStatus == DownloadStatus.PAUSE)
{ {
// 降低CPU占用 throw new OperationCanceledException("Stop thread by pause");
Thread.Sleep(100);
} }
downloading.DownloadStatusTitle = DictionaryResource.GetString("Waiting");
int maxDownloading = SettingsManager.GetInstance().GetAriaMaxConcurrentDownloads();
int downloadingCount;
do
{
downloadingCount = 0;
foreach (DownloadingItem item in downloadingList)
{
if (item.Downloading.DownloadStatus == DownloadStatus.DOWNLOADING)
{
downloadingCount++;
}
}
// 降低CPU占用
Thread.Sleep(100);
} while (downloadingCount > maxDownloading);
downloading.DownloadStatusTitle = oldStatus;
} }
/// <summary> /// <summary>
@ -958,38 +947,55 @@ namespace DownKyi.Services.Download
// path已斜杠结尾去掉斜杠 // path已斜杠结尾去掉斜杠
path = path.TrimEnd('/').TrimEnd('\\'); path = path.TrimEnd('/').TrimEnd('\\');
AriaSendOption option = new AriaSendOption //检查gid对应任务如果已创建那么直接使用
{ //但是代理设置会出现不能随时更新的问题
//HttpProxy = $"http://{Settings.GetAriaHttpProxy()}:{Settings.GetAriaHttpProxyListenPort()}",
Dir = path,
Out = localFileName
//Header = $"cookie: {Login.GetLoginInfoCookiesString()}\nreferer: https://www.bilibili.com",
//UseHead = "true",
//UserAgent = Utils.GetUserAgent()
};
// 如果设置了代理则增加HttpProxy if (downloading.Downloading.Gid != null)
if (SettingsManager.GetInstance().IsAriaHttpProxy() == AllowStatus.YES)
{ {
option.HttpProxy = $"http://{SettingsManager.GetInstance().GetAriaHttpProxy()}:{SettingsManager.GetInstance().GetAriaHttpProxyListenPort()}"; Task<AriaTellStatus> status = AriaClient.TellStatus(downloading.Downloading.Gid);
if (status == null || status.Result == null)
downloading.Downloading.Gid = null;
} }
// 添加一个下载 if (downloading.Downloading.Gid == null)
Task<AriaAddUri> ariaAddUri = AriaClient.AddUriAsync(urls, option);
if (ariaAddUri == null || ariaAddUri.Result == null || ariaAddUri.Result.Result == null)
{ {
return DownloadResult.FAILED; AriaSendOption option = new AriaSendOption
} {
//HttpProxy = $"http://{Settings.GetAriaHttpProxy()}:{Settings.GetAriaHttpProxyListenPort()}",
Dir = path,
Out = localFileName
//Header = $"cookie: {Login.GetLoginInfoCookiesString()}\nreferer: https://www.bilibili.com",
//UseHead = "true",
//UserAgent = Utils.GetUserAgent()
};
// 如果设置了代理则增加HttpProxy
if (SettingsManager.GetInstance().IsAriaHttpProxy() == AllowStatus.YES)
{
option.HttpProxy = $"http://{SettingsManager.GetInstance().GetAriaHttpProxy()}:{SettingsManager.GetInstance().GetAriaHttpProxyListenPort()}";
}
// 添加一个下载
Task<AriaAddUri> ariaAddUri = AriaClient.AddUriAsync(urls, option);
if (ariaAddUri == null || ariaAddUri.Result == null || ariaAddUri.Result.Result == null)
{
return DownloadResult.FAILED;
}
// 保存gid // 保存gid
string gid = ariaAddUri.Result.Result; string gid = ariaAddUri.Result.Result;
downloading.Downloading.Gid = gid; downloading.Downloading.Gid = gid;
}
else
{
Task<AriaPause> ariaUnpause = AriaClient.UnpauseAsync(downloading.Downloading.Gid);
}
// 管理下载 // 管理下载
AriaManager ariaManager = new AriaManager(); AriaManager ariaManager = new AriaManager();
ariaManager.TellStatus += AriaTellStatus; ariaManager.TellStatus += AriaTellStatus;
ariaManager.DownloadFinish += AriaDownloadFinish; ariaManager.DownloadFinish += AriaDownloadFinish;
return ariaManager.GetDownloadStatus(gid, new Action(() => return ariaManager.GetDownloadStatus(downloading.Downloading.Gid, new Action(() =>
{ {
switch (downloading.Downloading.DownloadStatus) switch (downloading.Downloading.DownloadStatus)
{ {
@ -999,7 +1005,6 @@ namespace DownKyi.Services.Download
Pause(downloading); Pause(downloading);
break; break;
case DownloadStatus.DOWNLOADING: case DownloadStatus.DOWNLOADING:
Task<AriaPause> ariaUnpause = AriaClient.UnpauseAsync(downloading.Downloading.Gid);
break; break;
} }
})); }));

Loading…
Cancel
Save