支持杜比全景声、杜比视界

croire 3 years ago
parent c664ecd9f6
commit 0a37220fe9

@ -6,6 +6,8 @@ namespace DownKyi.Core.BiliApi.BiliUtils
{
private static readonly List<Quality> resolutions = new List<Quality>
{
new Quality { Name = "超高清 8K", Id = 127 },
new Quality { Name = "杜比视界", Id = 126 },
new Quality { Name = "HDR 真彩", Id = 125 },
new Quality { Name = "4K 超清", Id = 120 },
new Quality { Name = "1080P 60帧", Id = 116 },
@ -22,6 +24,7 @@ namespace DownKyi.Core.BiliApi.BiliUtils
new Quality { Name = "64K", Id = 30216 },
new Quality { Name = "132K", Id = 30232 },
new Quality { Name = "192K", Id = 30280 },
new Quality { Name = "Dolby Atmos", Id = 30250 },
};
/// <summary>

@ -16,5 +16,7 @@ namespace DownKyi.Core.BiliApi.VideoStream.Models
public List<PlayUrlDashVideo> Video { get; set; }
[JsonProperty("audio")]
public List<PlayUrlDashVideo> Audio { get; set; }
[JsonProperty("dolby")]
public PlayUrlDashDolby Dolby { get; set; }
}
}

@ -0,0 +1,13 @@
using DownKyi.Core.BiliApi.Models;
using Newtonsoft.Json;
using System.Collections.Generic;
namespace DownKyi.Core.BiliApi.VideoStream.Models
{
public class PlayUrlDashDolby : BaseModel
{
// type
[JsonProperty("audio")]
public List<PlayUrlDashVideo> Audio { get; set; }
}
}

@ -8,9 +8,9 @@ namespace DownKyi.Core.BiliApi.VideoStream.Models
{
[JsonProperty("id")]
public int Id { get; set; }
[JsonProperty("baseUrl")]
[JsonProperty("base_url")]
public string BaseUrl { get; set; }
[JsonProperty("backupUrl")]
[JsonProperty("backup_url")]
public List<string> BackupUrl { get; set; }
// bandwidth
[JsonProperty("mimeType")]

@ -93,7 +93,7 @@ namespace DownKyi.Core.BiliApi.VideoStream
/// <returns></returns>
public static PlayUrl GetVideoPlayUrl(long avid, string bvid, long cid, int quality = 125)
{
string baseUrl = $"https://api.bilibili.com/x/player/playurl?cid={cid}&qn={quality}&fourk=1&fnver=0&fnval=80";
string baseUrl = $"https://api.bilibili.com/x/player/playurl?cid={cid}&qn={quality}&fourk=1&fnver=0&fnval=4048";
string url;
if (bvid != null) { url = $"{baseUrl}&bvid={bvid}"; }
else if (avid > -1) { url = $"{baseUrl}&aid={avid}"; }
@ -112,7 +112,7 @@ namespace DownKyi.Core.BiliApi.VideoStream
/// <returns></returns>
public static PlayUrl GetBangumiPlayUrl(long avid, string bvid, long cid, int quality = 125)
{
string baseUrl = $"https://api.bilibili.com/pgc/player/web/playurl?cid={cid}&qn={quality}&fourk=1&fnver=0&fnval=80";
string baseUrl = $"https://api.bilibili.com/pgc/player/web/playurl?cid={cid}&qn={quality}&fourk=1&fnver=0&fnval=4048";
string url;
if (bvid != null) { url = $"{baseUrl}&bvid={bvid}"; }
else if (avid > -1) { url = $"{baseUrl}&aid={avid}"; }
@ -131,7 +131,7 @@ namespace DownKyi.Core.BiliApi.VideoStream
/// <returns></returns>
public static PlayUrl GetCheesePlayUrl(long avid, string bvid, long cid, long episodeId, int quality = 125)
{
string baseUrl = $"https://api.bilibili.com/pugv/player/web/playurl?cid={cid}&qn={quality}&fourk=1&fnver=0&fnval=80";
string baseUrl = $"https://api.bilibili.com/pugv/player/web/playurl?cid={cid}&qn={quality}&fourk=1&fnver=0&fnval=4048";
string url;
if (bvid != null) { url = $"{baseUrl}&bvid={bvid}"; }
else if (avid > -1) { url = $"{baseUrl}&aid={avid}"; }

@ -49,7 +49,13 @@ namespace DownKyi.Core.BiliApi
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Method = method;
request.Timeout = 30 * 1000;
request.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36";
// MacOS Safari
string safari = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1.1 Safari/605.1.15";
// Windows 10 Chrome
string chrome = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36";
request.UserAgent = chrome;
//request.ContentType = "application/json,text/html,application/xhtml+xml,application/xml;charset=UTF-8";
request.Headers["accept-language"] = "zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7";
request.Headers["accept-encoding"] = "gzip, deflate, br";

@ -211,6 +211,7 @@
<Compile Include="BiliApi\VideoStream\Models\PlayerV2.cs" />
<Compile Include="BiliApi\VideoStream\Models\PlayUrl.cs" />
<Compile Include="BiliApi\VideoStream\Models\PlayUrlDash.cs" />
<Compile Include="BiliApi\VideoStream\Models\PlayUrlDashDolby.cs" />
<Compile Include="BiliApi\VideoStream\Models\PlayUrlDashVideo.cs" />
<Compile Include="BiliApi\VideoStream\Models\PlayUrlDurl.cs" />
<Compile Include="BiliApi\VideoStream\Models\PlayUrlSupportFormat.cs" />

@ -1,15 +1,31 @@
using System.Collections.Generic;
using System.Collections.ObjectModel;
namespace DownKyi.Core.Utils
{
public static class ListHelper
{
/// <summary>
/// 判断ObservableCollection中是否存在不存在则添加
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="list"></param>
/// <param name="item"></param>
public static void AddUnique<T>(ObservableCollection<T> list, T item)
{
if (!list.Contains(item))
{
list.Add(item);
}
}
/// <summary>
/// 判断List中是否存在不存在则添加
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="list"></param>
/// <param name="item"></param>
public static void AddUnique<T>(List<T> list, T item)
{
if (!list.Exists(t => t.Equals(item)))

@ -119,6 +119,15 @@ namespace DownKyi.Services.Download
}
};
}
// 将所有视频设置为选中
foreach (VideoSection section in videoSections)
{
foreach (var item in section.VideoPages)
{
item.IsSelected = true;
}
}
}
/// <summary>
@ -200,6 +209,9 @@ namespace DownKyi.Services.Download
{
foreach (VideoPage page in section.VideoPages)
{
// 只下载选中项,跳过未选中项
if (!page.IsSelected) { continue; }
// 没有解析的也跳过
if (page.PlayUrl == null) { continue; }
@ -282,7 +294,7 @@ namespace DownKyi.Services.Download
.SetVideoZone(videoInfoView.VideoZone.Split('>')[0])
.SetAudioQuality(page.AudioQualityFormat)
.SetVideoQuality(page.VideoQuality == null ? "" : page.VideoQuality.QualityFormat)
.SetVideoCodec(page.VideoQuality == null ? "" : page.VideoQuality.SelectedVideoCodec.Contains("AVC") ? "AVC" : page.VideoQuality.SelectedVideoCodec.Contains("HEVC") ? "HEVC" : "");
.SetVideoCodec(page.VideoQuality == null ? "" : page.VideoQuality.SelectedVideoCodec.Contains("AVC") ? "AVC" : page.VideoQuality.SelectedVideoCodec.Contains("HEVC") ? "HEVC" : page.VideoQuality.SelectedVideoCodec.Contains("Dolby") ? "Dolby Vision" : "");
string filePath = Path.Combine(directory, fileName.RelativePath());
// 视频类别

@ -71,6 +71,17 @@ namespace DownKyi.Services.Download
}
}
// 避免Dolby==null及其它未知情况直接使用异常捕获
try
{
// Dolby Atmos
if (downloading.AudioCodec.Id == 30250)
{
downloadAudio = downloading.PlayUrl.Dash.Dolby.Audio[0];
}
}
catch (Exception) { }
return DownloadVideo(downloading, downloadAudio);
}
@ -892,7 +903,7 @@ namespace DownKyi.Services.Download
$"Cookie: {LoginHelper.GetLoginInfoCookiesString()}",
$"Origin: https://www.bilibili.com",
$"Referer: https://www.bilibili.com",
$"User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit / 537.36(KHTML, like Gecko) Chrome / 91.0.4472.77 Safari / 537.36"
$"User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36"
};
AriaConfig config = new AriaConfig()

@ -5,6 +5,7 @@ using DownKyi.Core.Settings.Models;
using DownKyi.Core.Utils;
using DownKyi.ViewModels.PageViewModels;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
namespace DownKyi.Services
@ -94,13 +95,13 @@ namespace DownKyi.Services
/// <param name="playUrl"></param>
/// <param name="defaultAudioQuality"></param>
/// <returns></returns>
private static List<string> GetAudioQualityFormatList(PlayUrl playUrl, int defaultAudioQuality)
private static ObservableCollection<string> GetAudioQualityFormatList(PlayUrl playUrl, int defaultAudioQuality)
{
List<string> audioQualityFormatList = new List<string>();
if (playUrl.Dash.Audio == null)
{
return audioQualityFormatList;
return new ObservableCollection<string>();
}
foreach (PlayUrlDashVideo audio in playUrl.Dash.Audio)
@ -118,7 +119,7 @@ namespace DownKyi.Services
audioQualityFormatList.Sort(new StringLogicalComparer<string>());
audioQualityFormatList.Reverse();
return audioQualityFormatList;
return new ObservableCollection<string>(audioQualityFormatList);
}
/// <summary>
@ -221,7 +222,7 @@ namespace DownKyi.Services
/// <returns></returns>
internal static string GetVideoCodecName(string origin)
{
return origin.Contains("avc") ? "H.264/AVC" : origin.Contains("hev") ? "H.265/HEVC" : origin.Contains("dvh") ? "dolby" : "";
return origin.Contains("avc") ? "H.264/AVC" : origin.Contains("hev") ? "H.265/HEVC" : origin.Contains("dvh") || origin.Contains("hvc") ? "Dolby Vision" : "";
}
}

@ -1,6 +1,10 @@
using DownKyi.Core.BiliApi.VideoStream.Models;
using DownKyi.Core.BiliApi.BiliUtils;
using DownKyi.Core.BiliApi.VideoStream.Models;
using DownKyi.Core.Utils;
using Prism.Commands;
using Prism.Mvvm;
using System.Collections.Generic;
using System.Collections.ObjectModel;
namespace DownKyi.ViewModels.PageViewModels
{
@ -43,8 +47,8 @@ namespace DownKyi.ViewModels.PageViewModels
set => SetProperty(ref duration, value);
}
private List<string> audioQualityFormatList;
public List<string> AudioQualityFormatList
private ObservableCollection<string> audioQualityFormatList;
public ObservableCollection<string> AudioQualityFormatList
{
get => audioQualityFormatList;
set => SetProperty(ref audioQualityFormatList, value);
@ -71,5 +75,37 @@ namespace DownKyi.ViewModels.PageViewModels
set => SetProperty(ref videoQuality, value);
}
#region
// 视频画质选择事件
private DelegateCommand videoQualitySelectedCommand;
public DelegateCommand VideoQualitySelectedCommand => videoQualitySelectedCommand ?? (videoQualitySelectedCommand = new DelegateCommand(ExecuteVideoQualitySelectedCommand));
/// <summary>
/// 视频画质选择事件
/// </summary>
private void ExecuteVideoQualitySelectedCommand()
{
// 杜比视界
string dolby = Constant.GetAudioQualities()[3].Name;
if (VideoQuality.Quality == 126)
{
ListHelper.AddUnique(AudioQualityFormatList, dolby);
AudioQualityFormat = dolby;
}
else
{
if (AudioQualityFormatList.Contains(dolby))
{
AudioQualityFormatList.Remove(dolby);
AudioQualityFormat = AudioQualityFormatList[0];
}
}
}
#endregion
}
}

@ -125,6 +125,7 @@ namespace DownKyi.ViewModels.Settings
// 优先下载音质
AudioQualityList = Constant.GetAudioQualities();
AudioQualityList.RemoveAt(3);
// 文件命名格式
SelectedFileName = new ObservableCollection<DisplayFileNamePart>();

@ -619,14 +619,14 @@
DisplayMemberBinding="{Binding Order}"
Header="{DynamicResource Order}" />
<GridViewColumn
Width="550"
Width="540"
DisplayMemberBinding="{Binding Name}"
Header="{DynamicResource Name}" />
<GridViewColumn
Width="100"
DisplayMemberBinding="{Binding Duration}"
Header="{DynamicResource Duration}" />
<GridViewColumn Width="100" Header="{DynamicResource AudioQuality}">
<GridViewColumn Width="120" Header="{DynamicResource AudioQuality}">
<GridViewColumn.CellTemplate>
<DataTemplate>
<Grid>
@ -644,7 +644,13 @@
IsSynchronizedWithCurrentItem="True"
ItemsSource="{Binding VideoQualityList, Mode=TwoWay, IsAsync=True}"
SelectedItem="{Binding VideoQuality, Mode=TwoWay}"
SelectedValuePath="Quality" />
SelectedValuePath="Quality">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<i:InvokeCommandAction Command="{Binding VideoQualitySelectedCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</ComboBox>
</Grid>
</DataTemplate>
</GridViewColumn.CellTemplate>

Loading…
Cancel
Save