修复下载中的一些问题

pull/252/head
flyself 3 years ago
parent 871f60df6b
commit 9f443cb809

@ -9,8 +9,8 @@
- [x] 支持4K下载 - [x] 支持4K下载
- [x] 支持视频、番剧、剧集、电影、课程下载 - [x] 支持视频、番剧、剧集、电影、课程下载
- [x] **支持用户收藏夹、订阅、稍后再看、历史记录下载** - [x] **支持用户收藏夹、订阅、稍后再看、历史记录下载**
- [x] ~~**支持港澳台番剧下载,解除地区限制**~~
- [x] 支持弹幕下载、样式设置 - [x] 支持弹幕下载、样式设置
- [x] 支持字幕下载
- [x] 支持封面下载 - [x] 支持封面下载
- [x] 支持断点续传 - [x] 支持断点续传
- [x] 支持Aria2c - [x] 支持Aria2c
@ -20,6 +20,7 @@
- [x] 支持音视频分离 - [x] 支持音视频分离
- [x] 支持去水印 - [x] 支持去水印
- [x] 支持检查更新 - [x] 支持检查更新
……
## 使用方法 ## 使用方法

@ -4,25 +4,43 @@ namespace DownKyi.Core.BiliApi.BiliUtils
{ {
public static class Constant public static class Constant
{ {
private static readonly List<Quality> resolutions = new List<Quality>
{
new Quality { Name = "HDR 真彩", Id = 125 },
new Quality { Name = "4K 超清", Id = 120 },
new Quality { Name = "1080P 60帧", Id = 116 },
new Quality { Name = "1080P 高码率", Id = 112 },
new Quality { Name = "1080P 高清", Id = 80 },
new Quality { Name = "720P 60帧", Id = 74 },
new Quality { Name = "720P 高清", Id = 64 },
new Quality { Name = "480P 清晰", Id = 32 },
new Quality { Name = "360P 流畅", Id = 16 },
};
private static readonly List<Quality> qualities = new List<Quality>
{
new Quality { Name = "64K", Id = 30216 },
new Quality { Name = "132K", Id = 30232 },
new Quality { Name = "192K", Id = 30280 },
};
/// <summary> /// <summary>
/// 音质id及含义 /// 获取支持的视频画质
/// </summary> /// </summary>
public static Dictionary<int, string> AudioQuality { get; } = new Dictionary<int, string>() /// <returns></returns>
public static List<Quality> GetResolutions()
{ {
{ 30216, "64K" }, return resolutions;
{ 30232, "132K" }, }
{ 30280, "192K" }
};
/// <summary> /// <summary>
/// 音质id及含义 /// 获取支持的视频音质
/// </summary> /// </summary>
public static Dictionary<string, int> AudioQualityId { get; } = new Dictionary<string, int>() /// <returns></returns>
public static List<Quality> GetAudioQualities()
{ {
{ "64K", 30216 }, return qualities;
{ "132K", 30232 }, }
{ "192K", 30280 }
};
} }
} }

@ -0,0 +1,8 @@
namespace DownKyi.Core.BiliApi.BiliUtils
{
public class Quality
{
public string Name { get; set; }
public int Id { get; set; }
}
}

@ -36,16 +36,16 @@
<Reference Include="Brotli.Core, Version=2.1.1.0, Culture=neutral, processorArchitecture=MSIL"> <Reference Include="Brotli.Core, Version=2.1.1.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Brotli.NET.2.1.1\lib\net45\Brotli.Core.dll</HintPath> <HintPath>..\packages\Brotli.NET.2.1.1\lib\net45\Brotli.Core.dll</HintPath>
</Reference> </Reference>
<Reference Include="Google.Protobuf, Version=3.18.1.0, Culture=neutral, PublicKeyToken=a7d26565bac4d604, processorArchitecture=MSIL"> <Reference Include="Google.Protobuf, Version=3.19.1.0, Culture=neutral, PublicKeyToken=a7d26565bac4d604, processorArchitecture=MSIL">
<HintPath>..\packages\Google.Protobuf.3.18.1\lib\net45\Google.Protobuf.dll</HintPath> <HintPath>..\packages\Google.Protobuf.3.19.1\lib\net45\Google.Protobuf.dll</HintPath>
</Reference> </Reference>
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL"> <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> <HintPath>..\packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference> </Reference>
<Reference Include="PresentationCore" /> <Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" /> <Reference Include="PresentationFramework" />
<Reference Include="QRCoder, Version=1.4.1.0, Culture=neutral, processorArchitecture=MSIL"> <Reference Include="QRCoder, Version=1.4.3.0, Culture=neutral, PublicKeyToken=c4ed5b9ae8358a28, processorArchitecture=MSIL">
<HintPath>..\packages\QRCoder.1.4.1\lib\net40\QRCoder.dll</HintPath> <HintPath>..\packages\QRCoder.1.4.3\lib\net40\QRCoder.dll</HintPath>
</Reference> </Reference>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Buffers, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL"> <Reference Include="System.Buffers, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
@ -64,8 +64,8 @@
<Reference Include="System.Numerics.Vectors, Version=4.1.4.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> <Reference Include="System.Numerics.Vectors, Version=4.1.4.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll</HintPath> <HintPath>..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll</HintPath>
</Reference> </Reference>
<Reference Include="System.Runtime.CompilerServices.Unsafe, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> <Reference Include="System.Runtime.CompilerServices.Unsafe, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Runtime.CompilerServices.Unsafe.5.0.0\lib\net45\System.Runtime.CompilerServices.Unsafe.dll</HintPath> <HintPath>..\packages\System.Runtime.CompilerServices.Unsafe.6.0.0\lib\net461\System.Runtime.CompilerServices.Unsafe.dll</HintPath>
</Reference> </Reference>
<Reference Include="System.Runtime.InteropServices.RuntimeInformation, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> <Reference Include="System.Runtime.InteropServices.RuntimeInformation, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Runtime.InteropServices.RuntimeInformation.4.3.0\lib\net45\System.Runtime.InteropServices.RuntimeInformation.dll</HintPath> <HintPath>..\packages\System.Runtime.InteropServices.RuntimeInformation.4.3.0\lib\net45\System.Runtime.InteropServices.RuntimeInformation.dll</HintPath>
@ -129,6 +129,7 @@
<Compile Include="BiliApi\Bangumi\Models\BangumiUpInfo.cs" /> <Compile Include="BiliApi\Bangumi\Models\BangumiUpInfo.cs" />
<Compile Include="BiliApi\BiliUtils\Constant.cs" /> <Compile Include="BiliApi\BiliUtils\Constant.cs" />
<Compile Include="BiliApi\BiliUtils\ParseEntrance.cs" /> <Compile Include="BiliApi\BiliUtils\ParseEntrance.cs" />
<Compile Include="BiliApi\BiliUtils\Quality.cs" />
<Compile Include="BiliApi\Cheese\CheeseInfo.cs" /> <Compile Include="BiliApi\Cheese\CheeseInfo.cs" />
<Compile Include="BiliApi\Cheese\Models\CheeseBrief.cs" /> <Compile Include="BiliApi\Cheese\Models\CheeseBrief.cs" />
<Compile Include="BiliApi\Cheese\Models\CheeseEpisode.cs" /> <Compile Include="BiliApi\Cheese\Models\CheeseEpisode.cs" />
@ -279,8 +280,8 @@
</PropertyGroup> </PropertyGroup>
<Error Condition="!Exists('..\packages\Brotli.NET.2.1.1\build\Brotli.NET.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Brotli.NET.2.1.1\build\Brotli.NET.targets'))" /> <Error Condition="!Exists('..\packages\Brotli.NET.2.1.1\build\Brotli.NET.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Brotli.NET.2.1.1\build\Brotli.NET.targets'))" />
<Error Condition="!Exists('..\packages\System.Data.SQLite.Core.1.0.112.2\build\net40\System.Data.SQLite.Core.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\System.Data.SQLite.Core.1.0.112.2\build\net40\System.Data.SQLite.Core.targets'))" /> <Error Condition="!Exists('..\packages\System.Data.SQLite.Core.1.0.112.2\build\net40\System.Data.SQLite.Core.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\System.Data.SQLite.Core.1.0.112.2\build\net40\System.Data.SQLite.Core.targets'))" />
<Error Condition="!Exists('..\packages\Google.Protobuf.Tools.3.18.1\build\Google.Protobuf.Tools.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Google.Protobuf.Tools.3.18.1\build\Google.Protobuf.Tools.targets'))" /> <Error Condition="!Exists('..\packages\Google.Protobuf.Tools.3.19.1\build\Google.Protobuf.Tools.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Google.Protobuf.Tools.3.19.1\build\Google.Protobuf.Tools.targets'))" />
</Target> </Target>
<Import Project="..\packages\System.Data.SQLite.Core.1.0.112.2\build\net40\System.Data.SQLite.Core.targets" Condition="Exists('..\packages\System.Data.SQLite.Core.1.0.112.2\build\net40\System.Data.SQLite.Core.targets')" /> <Import Project="..\packages\System.Data.SQLite.Core.1.0.112.2\build\net40\System.Data.SQLite.Core.targets" Condition="Exists('..\packages\System.Data.SQLite.Core.1.0.112.2\build\net40\System.Data.SQLite.Core.targets')" />
<Import Project="..\packages\Google.Protobuf.Tools.3.18.1\build\Google.Protobuf.Tools.targets" Condition="Exists('..\packages\Google.Protobuf.Tools.3.18.1\build\Google.Protobuf.Tools.targets')" /> <Import Project="..\packages\Google.Protobuf.Tools.3.19.1\build\Google.Protobuf.Tools.targets" Condition="Exists('..\packages\Google.Protobuf.Tools.3.19.1\build\Google.Protobuf.Tools.targets')" />
</Project> </Project>

@ -10,7 +10,7 @@ using System.Runtime.InteropServices;
[assembly: AssemblyConfiguration("")] [assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("DownKyi")] [assembly: AssemblyCompany("DownKyi")]
[assembly: AssemblyProduct("DownKyi.Core")] [assembly: AssemblyProduct("DownKyi.Core")]
[assembly: AssemblyCopyright("Copyright © 2021")] [assembly: AssemblyCopyright("Copyright © Downkyi 2020-2021")]
[assembly: AssemblyTrademark("")] [assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")] [assembly: AssemblyCulture("")]
@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值 //可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值
//通过使用 "*",如下所示: //通过使用 "*",如下所示:
// [assembly: AssemblyVersion("1.0.*")] // [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("2.0.0.0")] [assembly: AssemblyVersion("2.1.0.0")]
[assembly: AssemblyFileVersion("2.0.0.0")] [assembly: AssemblyFileVersion("2.1.0.0")]

@ -4,7 +4,7 @@
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly> <dependentAssembly>
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" /> <assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-5.0.0.0" newVersion="5.0.0.0" /> <bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly> </dependentAssembly>
</assemblyBinding> </assemblyBinding>
</runtime> </runtime>

@ -1,14 +1,14 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<packages> <packages>
<package id="Brotli.NET" version="2.1.1" targetFramework="net472" /> <package id="Brotli.NET" version="2.1.1" targetFramework="net472" />
<package id="Google.Protobuf" version="3.18.1" targetFramework="net472" /> <package id="Google.Protobuf" version="3.19.1" targetFramework="net472" />
<package id="Google.Protobuf.Tools" version="3.18.1" targetFramework="net472" /> <package id="Google.Protobuf.Tools" version="3.19.1" targetFramework="net472" />
<package id="Newtonsoft.Json" version="13.0.1" targetFramework="net472" /> <package id="Newtonsoft.Json" version="13.0.1" targetFramework="net472" />
<package id="QRCoder" version="1.4.1" targetFramework="net472" /> <package id="QRCoder" version="1.4.3" targetFramework="net472" />
<package id="System.Buffers" version="4.5.1" targetFramework="net472" /> <package id="System.Buffers" version="4.5.1" targetFramework="net472" />
<package id="System.Data.SQLite.Core" version="1.0.112.2" targetFramework="net472" /> <package id="System.Data.SQLite.Core" version="1.0.112.2" targetFramework="net472" />
<package id="System.Memory" version="4.5.4" targetFramework="net472" /> <package id="System.Memory" version="4.5.4" targetFramework="net472" />
<package id="System.Numerics.Vectors" version="4.5.0" targetFramework="net472" /> <package id="System.Numerics.Vectors" version="4.5.0" targetFramework="net472" />
<package id="System.Runtime.CompilerServices.Unsafe" version="5.0.0" targetFramework="net472" /> <package id="System.Runtime.CompilerServices.Unsafe" version="6.0.0" targetFramework="net472" />
<package id="System.Runtime.InteropServices.RuntimeInformation" version="4.3.0" targetFramework="net472" /> <package id="System.Runtime.InteropServices.RuntimeInformation" version="4.3.0" targetFramework="net472" />
</packages> </packages>

@ -96,7 +96,6 @@
<Compile Include="Models\DisplayFileNamePart.cs" /> <Compile Include="Models\DisplayFileNamePart.cs" />
<Compile Include="Models\ParseScopeDisplay.cs" /> <Compile Include="Models\ParseScopeDisplay.cs" />
<Compile Include="Models\PlayStreamType.cs" /> <Compile Include="Models\PlayStreamType.cs" />
<Compile Include="Models\Resolution.cs" />
<Compile Include="Models\TabHeader.cs" /> <Compile Include="Models\TabHeader.cs" />
<Compile Include="Models\VideoQuality.cs" /> <Compile Include="Models\VideoQuality.cs" />
<Compile Include="Models\VideoInfoView.cs" /> <Compile Include="Models\VideoInfoView.cs" />
@ -110,8 +109,6 @@
<Compile Include="Services\Download\IDownloadService.cs" /> <Compile Include="Services\Download\IDownloadService.cs" />
<Compile Include="Services\IFavoritesService.cs" /> <Compile Include="Services\IFavoritesService.cs" />
<Compile Include="Services\IInfoService.cs" /> <Compile Include="Services\IInfoService.cs" />
<Compile Include="Services\IResolutionService.cs" />
<Compile Include="Services\ResolutionService.cs" />
<Compile Include="Services\Utils.cs" /> <Compile Include="Services\Utils.cs" />
<Compile Include="Services\VideoInfoService.cs" /> <Compile Include="Services\VideoInfoService.cs" />
<Compile Include="Utils\ClipboardHooker.cs" /> <Compile Include="Utils\ClipboardHooker.cs" />

@ -119,6 +119,7 @@
<system:String x:Key="Video">视频</system:String> <system:String x:Key="Video">视频</system:String>
<system:String x:Key="FirstVideoCodecs">优先下载的视频编码:</system:String> <system:String x:Key="FirstVideoCodecs">优先下载的视频编码:</system:String>
<system:String x:Key="FirstVideoQuality">优先下载的视频画质:</system:String> <system:String x:Key="FirstVideoQuality">优先下载的视频画质:</system:String>
<system:String x:Key="FirstAudioQuality">优先下载的视频音质:</system:String>
<system:String x:Key="IsTranscodingFlvToMp4">下载FLV视频后转码为mp4</system:String> <system:String x:Key="IsTranscodingFlvToMp4">下载FLV视频后转码为mp4</system:String>
<system:String x:Key="IsUseDefaultDirectory">使用默认下载目录</system:String> <system:String x:Key="IsUseDefaultDirectory">使用默认下载目录</system:String>
<system:String x:Key="DefaultDirectory">默认下载目录:</system:String> <system:String x:Key="DefaultDirectory">默认下载目录:</system:String>
@ -136,6 +137,7 @@
<system:String x:Key="DisplayVideoQuality">画质</system:String> <system:String x:Key="DisplayVideoQuality">画质</system:String>
<system:String x:Key="DisplayVideoCodec">视频编码</system:String> <system:String x:Key="DisplayVideoCodec">视频编码</system:String>
<system:String x:Key="DisplaySpace">空格</system:String> <system:String x:Key="DisplaySpace">空格</system:String>
<system:String x:Key="Reset">恢复默认</system:String>
<system:String x:Key="SettingDanmaku">弹幕</system:String> <system:String x:Key="SettingDanmaku">弹幕</system:String>
<system:String x:Key="FilterType">按类型屏蔽</system:String> <system:String x:Key="FilterType">按类型屏蔽</system:String>

@ -1,4 +1,5 @@
using Prism.Mvvm; using DownKyi.Core.BiliApi.BiliUtils;
using Prism.Mvvm;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Windows.Media; using System.Windows.Media;
@ -38,6 +39,9 @@ namespace DownKyi.Models
// 视频封面的url // 视频封面的url
public string CoverUrl { get; set; } public string CoverUrl { get; set; }
// 视频page的封面的url
public string PageCoverUrl { get; set; }
private DrawingImage zoneImage; private DrawingImage zoneImage;
public DrawingImage ZoneImage public DrawingImage ZoneImage
{ {
@ -77,15 +81,6 @@ namespace DownKyi.Models
set => SetProperty(ref duration, value); set => SetProperty(ref duration, value);
} }
// 音频编码
public int AudioCodecId { get; set; }
private string audioCodecName;
public string AudioCodecName
{
get => audioCodecName;
set => SetProperty(ref audioCodecName, value);
}
// 视频编码 // 视频编码
// "hev1.2.4.L156.90" // "hev1.2.4.L156.90"
// "avc1.640034" // "avc1.640034"
@ -100,13 +95,21 @@ namespace DownKyi.Models
} }
// 视频画质 // 视频画质
private Resolution resolution; private Quality resolution;
public Resolution Resolution public Quality Resolution
{ {
get => resolution; get => resolution;
set => SetProperty(ref resolution, value); set => SetProperty(ref resolution, value);
} }
// 音频编码
private Quality audioCodec;
public Quality AudioCodec
{
get => audioCodec;
set => SetProperty(ref audioCodec, value);
}
// 文件路径,不包含扩展名,所有内容均以此路径下载 // 文件路径,不包含扩展名,所有内容均以此路径下载
public string FilePath { get; set; } public string FilePath { get; set; }

@ -59,7 +59,7 @@ namespace DownKyi.Services.Download
PlayUrlDashVideo downloadAudio = null; PlayUrlDashVideo downloadAudio = null;
foreach (PlayUrlDashVideo audio in downloading.PlayUrl.Dash.Audio) foreach (PlayUrlDashVideo audio in downloading.PlayUrl.Dash.Audio)
{ {
if (audio.Id == downloading.AudioCodecId) if (audio.Id == downloading.AudioCodec.Id)
{ {
downloadAudio = audio; downloadAudio = audio;
break; break;
@ -148,7 +148,7 @@ namespace DownKyi.Services.Download
/// 下载封面 /// 下载封面
/// </summary> /// </summary>
/// <param name="downloading"></param> /// <param name="downloading"></param>
public string DownloadCover(DownloadingItem downloading) public string DownloadCover(DownloadingItem downloading, string coverUrl, string fileName)
{ {
// 更新状态显示 // 更新状态显示
downloading.DownloadStatusTitle = DictionaryResource.GetString("WhileDownloading"); downloading.DownloadStatusTitle = DictionaryResource.GetString("WhileDownloading");
@ -160,24 +160,16 @@ namespace DownKyi.Services.Download
// 查询、保存封面 // 查询、保存封面
StorageCover storageCover = new StorageCover(); StorageCover storageCover = new StorageCover();
string cover = storageCover.GetCover(downloading.Avid, downloading.Bvid, downloading.Cid, downloading.CoverUrl); string cover = storageCover.GetCover(downloading.Avid, downloading.Bvid, downloading.Cid, coverUrl);
if (cover == null) if (cover == null)
{ {
return null; return null;
} }
// 图片的扩展名
string[] temp = downloading.CoverUrl.Split('.');
string fileExtension = temp[temp.Length - 1];
// 图片的地址
string coverPath = $"{StorageManager.GetCover()}/{cover}";
// 复制图片到指定位置 // 复制图片到指定位置
try try
{ {
string fileName = $"{downloading.FilePath}.{fileExtension}"; File.Copy(cover, fileName, true);
File.Copy(coverPath, fileName);
// 记录本次下载的文件 // 记录本次下载的文件
downloading.DownloadFiles.Add(fileName); downloading.DownloadFiles.Add(fileName);
@ -448,6 +440,15 @@ namespace DownKyi.Services.Download
/// <returns></returns> /// <returns></returns>
private async void SingleDownload(DownloadingItem downloading) private async void SingleDownload(DownloadingItem downloading)
{ {
// 路径
string[] temp = downloading.FilePath.Split('/');
string path = downloading.FilePath.Replace(temp[temp.Length - 1], "");
// 路径不存在则创建
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
await Task.Run(new Action(() => await Task.Run(new Action(() =>
{ {
downloading.DownloadStatus = DownloadStatus.DOWNLOADING; downloading.DownloadStatus = DownloadStatus.DOWNLOADING;
@ -507,14 +508,24 @@ namespace DownKyi.Services.Download
// 如果需要下载封面 // 如果需要下载封面
if (downloading.NeedDownloadContent["downloadCover"]) if (downloading.NeedDownloadContent["downloadCover"])
{ {
outputCover = DownloadCover(downloading);
string fileName = $"{downloading.FilePath}.{GetImageExtension(downloading.PageCoverUrl)}";
// page的封面
outputCover = DownloadCover(downloading, downloading.PageCoverUrl, fileName);
// 封面
DownloadCover(downloading, downloading.CoverUrl, $"{path}/Cover.{GetImageExtension(downloading.CoverUrl)}");
} }
// 暂停 // 暂停
Pause(downloading); Pause(downloading);
// 混流 // 混流
string outputMedia = MixedFlow(downloading, audioUid, videoUid); string outputMedia = string.Empty;
if (downloading.NeedDownloadContent["downloadAudio"] || downloading.NeedDownloadContent["downloadVideo"])
{
outputMedia = MixedFlow(downloading, audioUid, videoUid);
}
// 暂停 // 暂停
Pause(downloading); Pause(downloading);
@ -570,6 +581,24 @@ namespace DownKyi.Services.Download
})); }));
} }
/// <summary>
/// 获取图片的扩展名
/// </summary>
/// <param name="coverUrl"></param>
/// <returns></returns>
private string GetImageExtension(string coverUrl)
{
if (coverUrl == null)
{
return string.Empty;
}
// 图片的扩展名
string[] temp = coverUrl.Split('.');
string fileExtension = temp[temp.Length - 1];
return fileExtension;
}
/// <summary> /// <summary>
/// 强制暂停 /// 强制暂停
/// </summary> /// </summary>

@ -10,7 +10,7 @@ namespace DownKyi.Services.Download
string DownloadVideo(DownloadingItem downloading); string DownloadVideo(DownloadingItem downloading);
string DownloadDanmaku(DownloadingItem downloading); string DownloadDanmaku(DownloadingItem downloading);
List<string> DownloadSubtitle(DownloadingItem downloading); List<string> DownloadSubtitle(DownloadingItem downloading);
string DownloadCover(DownloadingItem downloading); string DownloadCover(DownloadingItem downloading, string coverUrl, string fileName);
string MixedFlow(DownloadingItem downloading, string audioUid, string videoUid); string MixedFlow(DownloadingItem downloading, string audioUid, string videoUid);
void Start(); void Start();

@ -1,4 +1,5 @@
using DownKyi.Core.BiliApi.VideoStream.Models; using DownKyi.Core.BiliApi.BiliUtils;
using DownKyi.Core.BiliApi.VideoStream.Models;
using DownKyi.Core.Settings; using DownKyi.Core.Settings;
using DownKyi.Core.Settings.Models; using DownKyi.Core.Settings.Models;
using DownKyi.Core.Utils; using DownKyi.Core.Utils;
@ -101,9 +102,10 @@ namespace DownKyi.Services
// 音质id大于设置画质时跳过 // 音质id大于设置画质时跳过
if (audio.Id > defaultAudioQuality) { continue; } if (audio.Id > defaultAudioQuality) { continue; }
if (Core.BiliApi.BiliUtils.Constant.AudioQuality.ContainsKey(audio.Id)) Quality audioQuality = Constant.GetAudioQualities().FirstOrDefault(t => { return t.Id == audio.Id; });
if (audioQuality != null)
{ {
ListHelper.AddUnique(audioQualityFormatList, Core.BiliApi.BiliUtils.Constant.AudioQuality[audio.Id]); ListHelper.AddUnique(audioQualityFormatList, audioQuality.Name);
} }
} }

@ -1,8 +1,8 @@
using DownKyi.Core.FileName; using DownKyi.Core.BiliApi.BiliUtils;
using DownKyi.Core.FileName;
using DownKyi.Core.Settings; using DownKyi.Core.Settings;
using DownKyi.Events; using DownKyi.Events;
using DownKyi.Models; using DownKyi.Models;
using DownKyi.Services;
using DownKyi.Utils; using DownKyi.Utils;
using Prism.Commands; using Prism.Commands;
using Prism.Events; using Prism.Events;
@ -36,20 +36,34 @@ namespace DownKyi.ViewModels.Settings
set => SetProperty(ref selectedVideoCodec, value); set => SetProperty(ref selectedVideoCodec, value);
} }
private List<Resolution> videoQualityList; private List<Quality> videoQualityList;
public List<Resolution> VideoQualityList public List<Quality> VideoQualityList
{ {
get => videoQualityList; get => videoQualityList;
set => SetProperty(ref videoQualityList, value); set => SetProperty(ref videoQualityList, value);
} }
private Resolution selectedVideoQuality; private Quality selectedVideoQuality;
public Resolution SelectedVideoQuality public Quality SelectedVideoQuality
{ {
get => selectedVideoQuality; get => selectedVideoQuality;
set => SetProperty(ref selectedVideoQuality, value); set => SetProperty(ref selectedVideoQuality, value);
} }
private List<Quality> audioQualityList;
public List<Quality> AudioQualityList
{
get => audioQualityList;
set => SetProperty(ref audioQualityList, value);
}
private Quality selectedAudioQuality;
public Quality SelectedAudioQuality
{
get => selectedAudioQuality;
set => SetProperty(ref selectedAudioQuality, value);
}
private bool isTranscodingFlvToMp4; private bool isTranscodingFlvToMp4;
public bool IsTranscodingFlvToMp4 public bool IsTranscodingFlvToMp4
{ {
@ -104,11 +118,14 @@ namespace DownKyi.ViewModels.Settings
VideoCodecs = new List<string> VideoCodecs = new List<string>
{ {
"H.264/AVC", "H.264/AVC",
"H.265/HEVC" "H.265/HEVC",
}; };
// 优先下载画质 // 优先下载画质
VideoQualityList = new ResolutionService().GetResolution(); VideoQualityList = Constant.GetResolutions();
// 优先下载音质
AudioQualityList = Constant.GetAudioQualities();
// 文件命名格式 // 文件命名格式
SelectedFileName = new ObservableCollection<DisplayFileNamePart>(); SelectedFileName = new ObservableCollection<DisplayFileNamePart>();
@ -143,6 +160,10 @@ namespace DownKyi.ViewModels.Settings
int quality = SettingsManager.GetInstance().GetQuality(); int quality = SettingsManager.GetInstance().GetQuality();
SelectedVideoQuality = VideoQualityList.FirstOrDefault(t => { return t.Id == quality; }); SelectedVideoQuality = VideoQualityList.FirstOrDefault(t => { return t.Id == quality; });
// 优先下载音质
int audioQuality = SettingsManager.GetInstance().GetAudioQuality();
SelectedAudioQuality = AudioQualityList.FirstOrDefault(t => { return t.Id == audioQuality; });
// 是否下载flv视频后转码为mp4 // 是否下载flv视频后转码为mp4
AllowStatus isTranscodingFlvToMp4 = SettingsManager.GetInstance().IsTranscodingFlvToMp4(); AllowStatus isTranscodingFlvToMp4 = SettingsManager.GetInstance().IsTranscodingFlvToMp4();
IsTranscodingFlvToMp4 = isTranscodingFlvToMp4 == AllowStatus.YES; IsTranscodingFlvToMp4 = isTranscodingFlvToMp4 == AllowStatus.YES;
@ -194,12 +215,28 @@ namespace DownKyi.ViewModels.Settings
/// <param name="parameter"></param> /// <param name="parameter"></param>
private void ExecuteVideoQualityCommand(object parameter) private void ExecuteVideoQualityCommand(object parameter)
{ {
if (!(parameter is Resolution resolution)) { return; } if (!(parameter is Quality resolution)) { return; }
bool isSucceed = SettingsManager.GetInstance().SetQuality(resolution.Id); bool isSucceed = SettingsManager.GetInstance().SetQuality(resolution.Id);
PublishTip(isSucceed); PublishTip(isSucceed);
} }
// 优先下载音质事件
private DelegateCommand<object> audioQualityCommand;
public DelegateCommand<object> AudioQualityCommand => audioQualityCommand ?? (audioQualityCommand = new DelegateCommand<object>(ExecuteAudioQualityCommand));
/// <summary>
/// 优先下载音质事件
/// </summary>
/// <param name="parameter"></param>
private void ExecuteAudioQualityCommand(object parameter)
{
if (!(parameter is Quality quality)) { return; }
bool isSucceed = SettingsManager.GetInstance().SetAudioQuality(quality.Id);
PublishTip(isSucceed);
}
// 是否下载flv视频后转码为mp4事件 // 是否下载flv视频后转码为mp4事件
private DelegateCommand isTranscodingFlvToMp4Command; private DelegateCommand isTranscodingFlvToMp4Command;
public DelegateCommand IsTranscodingFlvToMp4Command => isTranscodingFlvToMp4Command ?? (isTranscodingFlvToMp4Command = new DelegateCommand(ExecuteIsTranscodingFlvToMp4Command)); public DelegateCommand IsTranscodingFlvToMp4Command => isTranscodingFlvToMp4Command ?? (isTranscodingFlvToMp4Command = new DelegateCommand(ExecuteIsTranscodingFlvToMp4Command));
@ -307,6 +344,27 @@ namespace DownKyi.ViewModels.Settings
SelectedOptionalField = -1; SelectedOptionalField = -1;
} }
// 重置选中文件名字段
private DelegateCommand resetCommand;
public DelegateCommand ResetCommand => resetCommand ?? (resetCommand = new DelegateCommand(ExecuteResetCommand));
/// <summary>
/// 重置选中文件名字段
/// </summary>
private void ExecuteResetCommand()
{
bool isSucceed = SettingsManager.GetInstance().SetFileNameParts(null);
PublishTip(isSucceed);
List<FileNamePart> fileNameParts = SettingsManager.GetInstance().GetFileNameParts();
SelectedFileName.Clear();
foreach (FileNamePart item in fileNameParts)
{
string display = DisplayFileNamePart(item);
SelectedFileName.Add(new DisplayFileNamePart { Id = item, Title = display });
}
}
#endregion #endregion

@ -568,7 +568,7 @@ namespace DownKyi.ViewModels
// 如果存在正在下载列表,则跳过,并提示 // 如果存在正在下载列表,则跳过,并提示
foreach (DownloadingItem item in App.DownloadingList) foreach (DownloadingItem item in App.DownloadingList)
{ {
if (item.Cid == page.Cid && item.Resolution.Id == page.VideoQuality.Quality && item.AudioCodecName == page.AudioQualityFormat && item.VideoCodecName == page.VideoQuality.SelectedVideoCodec) if (item.Cid == page.Cid && item.Resolution.Id == page.VideoQuality.Quality && item.AudioCodec.Name == page.AudioQualityFormat && item.VideoCodecName == page.VideoQuality.SelectedVideoCodec)
{ {
eventAggregator.GetEvent<MessageEvent>().Publish($"{page.Name}{DictionaryResource.GetString("TipAlreadyToAddDownloading")}"); eventAggregator.GetEvent<MessageEvent>().Publish($"{page.Name}{DictionaryResource.GetString("TipAlreadyToAddDownloading")}");
continue; continue;
@ -578,7 +578,7 @@ namespace DownKyi.ViewModels
// 如果存在下载完成列表,弹出选择框是否再次下载 // 如果存在下载完成列表,弹出选择框是否再次下载
foreach (DownloadedItem item in App.DownloadedList) foreach (DownloadedItem item in App.DownloadedList)
{ {
if (item.Cid == page.Cid && item.Resolution.Id == page.VideoQuality.Quality && item.AudioCodecName == page.AudioQualityFormat && item.VideoCodecName == page.VideoQuality.SelectedVideoCodec) if (item.Cid == page.Cid && item.Resolution.Id == page.VideoQuality.Quality && item.AudioCodec.Name == page.AudioQualityFormat && item.VideoCodecName == page.VideoQuality.SelectedVideoCodec)
{ {
eventAggregator.GetEvent<MessageEvent>().Publish($"{page.Name}{DictionaryResource.GetString("TipAlreadyToAddDownloaded")}"); eventAggregator.GetEvent<MessageEvent>().Publish($"{page.Name}{DictionaryResource.GetString("TipAlreadyToAddDownloaded")}");
continue; continue;
@ -591,10 +591,17 @@ namespace DownKyi.ViewModels
ZoneAttr zone = zoneList.Find(it => it.Id == VideoInfoView.TypeId); ZoneAttr zone = zoneList.Find(it => it.Id == VideoInfoView.TypeId);
if (zone != null) if (zone != null)
{ {
ZoneAttr zoneParent = zoneList.Find(it => it.Id == zone.ParentId); if (zone.ParentId == 0)
if (zoneParent != null)
{ {
zoneId = zoneParent.Id; zoneId = zone.Id;
}
else
{
ZoneAttr zoneParent = zoneList.Find(it => it.Id == zone.ParentId);
if (zoneParent != null)
{
zoneId = zoneParent.Id;
}
} }
} }
@ -663,22 +670,23 @@ namespace DownKyi.ViewModels
Cid = page.Cid, Cid = page.Cid,
EpisodeId = page.EpisodeId, EpisodeId = page.EpisodeId,
CoverUrl = page.FirstFrame, CoverUrl = VideoInfoView.CoverUrl,
PageCoverUrl = page.FirstFrame,
ZoneImage = (DrawingImage)Application.Current.Resources[VideoZoneIcon.Instance().GetZoneImageKey(zoneId)], ZoneImage = (DrawingImage)Application.Current.Resources[VideoZoneIcon.Instance().GetZoneImageKey(zoneId)],
Order = page.Order, Order = page.Order,
MainTitle = VideoInfoView.Title, MainTitle = VideoInfoView.Title,
Name = page.Name, Name = page.Name,
Duration = page.Duration, Duration = page.Duration,
AudioCodecId = Constant.AudioQualityId[page.AudioQualityFormat],
AudioCodecName = page.AudioQualityFormat,
VideoCodecName = page.VideoQuality.SelectedVideoCodec, VideoCodecName = page.VideoQuality.SelectedVideoCodec,
Resolution = new Resolution { Name = page.VideoQuality.QualityFormat, Id = page.VideoQuality.Quality }, Resolution = new Quality { Name = page.VideoQuality.QualityFormat, Id = page.VideoQuality.Quality },
AudioCodec = Constant.GetAudioQualities().FirstOrDefault(t => { return t.Name == page.AudioQualityFormat; }),
FilePath = filePath, FilePath = filePath,
PlayStreamType = playStreamType, PlayStreamType = playStreamType,
DownloadStatus = DownloadStatus.NOT_STARTED, DownloadStatus = DownloadStatus.NOT_STARTED,
}; };
// 需要下载的内容 // 需要下载的内容
downloading.NeedDownloadContent["downloadAudio"] = downloadAudio; downloading.NeedDownloadContent["downloadAudio"] = downloadAudio;
downloading.NeedDownloadContent["downloadVideo"] = downloadVideo; downloading.NeedDownloadContent["downloadVideo"] = downloadVideo;

@ -39,14 +39,24 @@
VerticalAlignment="Center" VerticalAlignment="Center"
FontSize="14" FontSize="14"
Foreground="{DynamicResource BrushTextDark}" Foreground="{DynamicResource BrushTextDark}"
TextTrimming="CharacterEllipsis" TextTrimming="CharacterEllipsis">
ToolTip="{Binding MainTitle}">
<TextBlock.Text> <TextBlock.Text>
<MultiBinding StringFormat="{}{0}-{1}"> <MultiBinding StringFormat="{}{0}-{1}-{2}">
<Binding Path="Order" /> <Binding Path="Order" />
<Binding Path="MainTitle" />
<Binding Path="Name" /> <Binding Path="Name" />
</MultiBinding> </MultiBinding>
</TextBlock.Text> </TextBlock.Text>
<TextBlock.ToolTip>
<TextBlock>
<TextBlock.Text>
<MultiBinding StringFormat="{}{0}-{1}">
<Binding Path="MainTitle" />
<Binding Path="Name" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</TextBlock.ToolTip>
</TextBlock> </TextBlock>
<TextBlock <TextBlock
@ -60,7 +70,7 @@
<Binding Path="Duration" /> <Binding Path="Duration" />
<Binding Path="Resolution.Name" /> <Binding Path="Resolution.Name" />
<Binding Path="VideoCodecName" /> <Binding Path="VideoCodecName" />
<Binding Path="AudioCodecName" /> <Binding Path="AudioCodec.Name" />
</MultiBinding> </MultiBinding>
</TextBlock.Text> </TextBlock.Text>
</TextBlock> </TextBlock>

@ -188,7 +188,7 @@
Grid.Column="2" Grid.Column="2"
FontSize="12" FontSize="12"
Foreground="{DynamicResource BrushTextDark}" Foreground="{DynamicResource BrushTextDark}"
Text="3.17.3" /> Text="3.19.1" />
<TextBlock <TextBlock
Grid.Row="2" Grid.Row="2"
Grid.Column="3" Grid.Column="3"
@ -269,7 +269,7 @@
Grid.Column="2" Grid.Column="2"
FontSize="12" FontSize="12"
Foreground="{DynamicResource BrushTextDark}" Foreground="{DynamicResource BrushTextDark}"
Text="1.4.1" /> Text="1.4.3" />
<TextBlock <TextBlock
Grid.Row="5" Grid.Row="5"
Grid.Column="3" Grid.Column="3"

@ -54,6 +54,28 @@
</ComboBox> </ComboBox>
</StackPanel> </StackPanel>
<StackPanel Margin="0,20,0,0" Orientation="Horizontal">
<TextBlock
VerticalAlignment="Center"
FontSize="12"
Foreground="{DynamicResource BrushTextDark}"
Text="{DynamicResource FirstAudioQuality}" />
<ComboBox
Name="nameAudioQualityList"
Width="120"
VerticalContentAlignment="Center"
DisplayMemberPath="Name"
ItemsSource="{Binding AudioQualityList}"
SelectedItem="{Binding SelectedAudioQuality}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<i:InvokeCommandAction Command="{Binding AudioQualityCommand}" CommandParameter="{Binding ElementName=nameAudioQualityList, Path=SelectedItem}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</ComboBox>
</StackPanel>
<CheckBox <CheckBox
Margin="0,20,0,0" Margin="0,20,0,0"
HorizontalAlignment="Left" HorizontalAlignment="Left"
@ -144,6 +166,7 @@
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition /> <RowDefinition />
<RowDefinition /> <RowDefinition />
<RowDefinition />
</Grid.RowDefinitions> </Grid.RowDefinitions>
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="100" /> <ColumnDefinition Width="100" />
@ -194,6 +217,18 @@
</i:EventTrigger> </i:EventTrigger>
</i:Interaction.Triggers> </i:Interaction.Triggers>
</ListBox> </ListBox>
<Button
Grid.Row="2"
Grid.Column="1"
Width="75"
Margin="0,20,0,0"
HorizontalAlignment="Right"
VerticalAlignment="Center"
Command="{Binding ResetCommand}"
Content="{DynamicResource Reset}"
FontSize="12"
Style="{StaticResource BtnBorderStyle}" />
</Grid> </Grid>
</GroupBox> </GroupBox>

@ -3,4 +3,12 @@
<startup> <startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" /> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
</startup> </startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration> </configuration>
Loading…
Cancel
Save