diff --git a/src/BiliLite.Packages/BiliLite.Packages.wapproj b/src/BiliLite.Packages/BiliLite.Packages.wapproj
index 2c6d46f1b..a1751f234 100644
--- a/src/BiliLite.Packages/BiliLite.Packages.wapproj
+++ b/src/BiliLite.Packages/BiliLite.Packages.wapproj
@@ -57,7 +57,7 @@
True
$(NoWarn);NU1702
..\BiliLite.UWP\BiliLite.UWP.csproj
- C4FA34A878A0528F84922932FEC6746BCBCA5CEA
+ FD3F8B8872537B6FE4A2319C0534D6A8AEE6D419
False
SHA256
False
diff --git a/src/BiliLite.UWP/App.xaml.cs b/src/BiliLite.UWP/App.xaml.cs
index 6bf51b5d5..3c970052b 100644
--- a/src/BiliLite.UWP/App.xaml.cs
+++ b/src/BiliLite.UWP/App.xaml.cs
@@ -7,6 +7,7 @@
using Microsoft.Toolkit.Uwp.Helpers;
using System;
using System.Runtime.InteropServices;
+using System.Threading.Tasks;
using Windows.ApplicationModel;
using Windows.ApplicationModel.Activation;
using Windows.ApplicationModel.Core;
@@ -18,7 +19,6 @@
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;
using BiliLite.Pages;
-using BiliLite.ViewModels.Download;
using Microsoft.Extensions.DependencyInjection;
namespace BiliLite
@@ -205,12 +205,26 @@ private async void InitBili()
//圆角
App.Current.Resources["ImageCornerRadius"] = new CornerRadius(SettingService.GetValue(SettingConstants.UI.IMAGE_CORNER_RADIUS, 0));
await AppHelper.SetRegions();
- var downloadViewModel = ServiceProvider.GetRequiredService();
- downloadViewModel.LoadDownloading();
- downloadViewModel.LoadDownloaded();
+ await InitDb();
+ try
+ {
+ var downloadService = ServiceProvider.GetRequiredService();
+ downloadService.LoadDownloading();
+ downloadService.LoadDownloaded();
+ }
+ catch (Exception ex)
+ {
+ logger.Error("初始化加载下载视频错误", ex);
+ }
VideoPlayHistoryHelper.LoadABPlayHistories(true);
}
+ private async Task InitDb()
+ {
+ var sqlMigrateService = ServiceProvider.GetRequiredService();
+ await sqlMigrateService.MigrateDatabase();
+ }
+
///
/// 导航到特定页失败时调用
///
diff --git a/src/BiliLite.UWP/Assets/DbMigrations/01-0_40704.sql b/src/BiliLite.UWP/Assets/DbMigrations/01-0_40704.sql
new file mode 100644
index 000000000..4d0e3f985
--- /dev/null
+++ b/src/BiliLite.UWP/Assets/DbMigrations/01-0_40704.sql
@@ -0,0 +1,28 @@
+-- 创建 DownloadedItems 表
+CREATE TABLE IF NOT EXISTS DownloadedItems (
+ "ID" TEXT NOT NULL CONSTRAINT "PK_DownloadedItems" PRIMARY KEY,
+ "IsSeason" INTEGER NOT NULL,
+ "CoverPath" TEXT NULL,
+ "Title" TEXT NULL,
+ "UpdateTime" TEXT NOT NULL,
+ "Path" TEXT NULL
+);
+
+-- 创建 DownloadedSubItems 表
+CREATE TABLE IF NOT EXISTS "DownloadedSubItems" (
+ "CID" TEXT NOT NULL CONSTRAINT "PK_DownloadedSubItems" PRIMARY KEY,
+ "EpisodeID" TEXT NULL,
+ "Title" TEXT NULL,
+ "IsDash" INTEGER NOT NULL,
+ "QualityID" INTEGER NOT NULL,
+ "QualityName" TEXT NULL,
+ "PathList" TEXT NULL,
+ "DanmakuPath" TEXT NULL,
+ "Index" INTEGER NOT NULL,
+ "FilePath" TEXT NULL,
+ "SubtitlePaths" TEXT NULL,
+ "DownloadedItemDTOID" TEXT NULL,
+ CONSTRAINT "FK_DownloadedSubItems_DownloadedItems_DownloadedItemDTOID" FOREIGN KEY ("DownloadedItemDTOID") REFERENCES "DownloadedItems" ("ID") ON DELETE RESTRICT
+);
+
+CREATE INDEX "IX_DownloadedSubItems_DownloadedItemDTOID" ON "DownloadedSubItems" ("DownloadedItemDTOID");
\ No newline at end of file
diff --git a/src/BiliLite.UWP/Assets/Icon/icon_view_point.png b/src/BiliLite.UWP/Assets/Icon/icon_view_point.png
new file mode 100644
index 000000000..29d825be8
Binary files /dev/null and b/src/BiliLite.UWP/Assets/Icon/icon_view_point.png differ
diff --git a/src/BiliLite.UWP/Assets/Text/bili-merge.md b/src/BiliLite.UWP/Assets/Text/bili-merge.md
new file mode 100644
index 000000000..1a3229b19
--- /dev/null
+++ b/src/BiliLite.UWP/Assets/Text/bili-merge.md
@@ -0,0 +1,21 @@
+## BiliLite 导出视频
+此功能需要BiliLite版本4.4.0及以上
+
+1. 打开BiliLite UWP -『下载』-『下载完成』选项卡
+
+2. 右键或长按需要导出的视频,选择『导出视频』
+
+
+
+如果是多集视频,可以点击『保存』图标按钮
+
+
+
+3. 选择导出视频的保存位置,等待导出完成即可。
+PS:首次使用需要解压FFmpeg,可能会耗时久一点。
+
+
+
+### 其他工具
+
+- [基于python的视频合并脚本 https://github.com/TPAXcc/biliuwp-lite.Mixer](https://github.com/TPAXcc/biliuwp-lite.Mixer)
\ No newline at end of file
diff --git a/src/BiliLite.UWP/Assets/Text/img/1433952792.png b/src/BiliLite.UWP/Assets/Text/img/1433952792.png
new file mode 100644
index 000000000..84abd212d
Binary files /dev/null and b/src/BiliLite.UWP/Assets/Text/img/1433952792.png differ
diff --git a/src/BiliLite.UWP/Assets/Text/img/2655001972.png b/src/BiliLite.UWP/Assets/Text/img/2655001972.png
new file mode 100644
index 000000000..01d94a533
Binary files /dev/null and b/src/BiliLite.UWP/Assets/Text/img/2655001972.png differ
diff --git a/src/BiliLite.UWP/Assets/Text/img/3382929121.png b/src/BiliLite.UWP/Assets/Text/img/3382929121.png
new file mode 100644
index 000000000..062a423d3
Binary files /dev/null and b/src/BiliLite.UWP/Assets/Text/img/3382929121.png differ
diff --git a/src/BiliLite.UWP/BiliLite.UWP.csproj b/src/BiliLite.UWP/BiliLite.UWP.csproj
index ec8ba788a..e27069185 100644
--- a/src/BiliLite.UWP/BiliLite.UWP.csproj
+++ b/src/BiliLite.UWP/BiliLite.UWP.csproj
@@ -206,7 +206,11 @@
+
+
+
+
@@ -222,6 +226,7 @@
+
@@ -258,7 +263,12 @@
+
+ MarkdownViewerPage.xaml
+
+
+
@@ -937,8 +947,10 @@
+
+
@@ -1040,6 +1052,9 @@
+
+
+
@@ -1052,6 +1067,7 @@
+
Designer
@@ -1159,6 +1175,10 @@
MSBuild:Compile
Designer
+
+ Designer
+ MSBuild:Compile
+
Designer
MSBuild:Compile
diff --git a/src/BiliLite.UWP/Controls/Player.xaml.cs b/src/BiliLite.UWP/Controls/Player.xaml.cs
index c92487750..2e87919e3 100644
--- a/src/BiliLite.UWP/Controls/Player.xaml.cs
+++ b/src/BiliLite.UWP/Controls/Player.xaml.cs
@@ -325,6 +325,7 @@ private MediaSourceConfig CreateFFmpegInteropConfig(string userAgent, string ref
if (referer != null && referer.Length > 0)
{
_ffmpegConfig.FFmpegOptions.Add("referer", referer);
+ _ffmpegConfig.FFmpegOptions.Add("headers", $"Referer: {referer}");
}
_ffmpegConfig.VideoDecoderMode = passthrough ? VideoDecoderMode.ForceSystemDecoder : VideoDecoderMode.ForceFFmpegSoftwareDecoder;
@@ -520,7 +521,7 @@ public async Task PlayerDashUseNative(BiliDashPlayUrlInfo dash
message = "创建MediaSource失败"
};
}
-
+
m_playerVideo.Source = MediaSource.CreateFromAdaptiveMediaSource(mediaSource);
Buffering = true;
@@ -665,6 +666,7 @@ public async Task PlayDashUseFFmpegInterop(BiliDashPlayUrlInfo
//关闭正在播放的视频
ClosePlay();
var _ffmpegConfig = CreateFFmpegInteropConfig(userAgent, referer);
+
if (isLocal)
{
diff --git a/src/BiliLite.UWP/Controls/PlayerControl.xaml b/src/BiliLite.UWP/Controls/PlayerControl.xaml
index 47ff1489f..cd047621e 100644
--- a/src/BiliLite.UWP/Controls/PlayerControl.xaml
+++ b/src/BiliLite.UWP/Controls/PlayerControl.xaml
@@ -13,6 +13,7 @@
xmlns:fa="using:FontAwesome5" xmlns:player="using:BiliLite.Modules.Player"
xmlns:common="using:BiliLite.Models.Common"
xmlns:player1="using:BiliLite.Models.Common.Player"
+ xmlns:modules="using:BiliLite.Modules"
d:DesignHeight="800"
d:DesignWidth="1000">
@@ -302,7 +303,7 @@
-
+
弹幕同屏密度(0为不限制)
- 弹幕字体
+ 弹幕字体
@@ -446,7 +447,7 @@
合并重复弹幕
-
+
屏蔽等级(0为不屏蔽) 级
@@ -605,10 +606,10 @@
DoubleTapped="Grid_DoubleTapped">
-
+
-
+
@@ -666,7 +667,7 @@
-
+
@@ -702,9 +703,15 @@
第一集
+
+
+
-
+
@@ -915,11 +922,49 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/BiliLite.UWP/Controls/PlayerControl.xaml.cs b/src/BiliLite.UWP/Controls/PlayerControl.xaml.cs
index 4f1c05275..9502f6d01 100644
--- a/src/BiliLite.UWP/Controls/PlayerControl.xaml.cs
+++ b/src/BiliLite.UWP/Controls/PlayerControl.xaml.cs
@@ -114,6 +114,8 @@ public BiliPlayUrlQualitesInfo playUrlInfo
set { _playUrlInfo = value; DoPropertyChanged("playUrlInfo"); }
}
+ private readonly bool m_autoSkipOpEdFlag = false;
+ private DispatcherTimer m_positionTimer;
DispatcherTimer danmuTimer;
///
/// 弹幕信息
@@ -149,6 +151,12 @@ public PlayerControl()
danmuTimer = new DispatcherTimer();
danmuTimer.Interval = TimeSpan.FromSeconds(1);
danmuTimer.Tick += DanmuTimer_Tick;
+
+ m_positionTimer = new DispatcherTimer() { Interval = TimeSpan.FromSeconds(1) };
+ m_positionTimer.Tick += PositionTimer_Tick;
+ m_autoSkipOpEdFlag = SettingService.GetValue(SettingConstants.Player.AUTO_SKIP_OP_ED,
+ SettingConstants.Player.DEFAULT_AUTO_SKIP_OP_ED);
+
this.Loaded += PlayerControl_Loaded;
this.Unloaded += PlayerControl_Unloaded;
m_playerKeyRightAction = (PlayerKeyRightAction)SettingService.GetValue(SettingConstants.Player.PLAYER_KEY_RIGHT_ACTION, (int)PlayerKeyRightAction.ControlProgress);
@@ -241,6 +249,7 @@ private async void PlayerControl_Loaded(object sender, RoutedEventArgs e)
danmuTimer.Start();
timer_focus.Start();
+ m_positionTimer.Start();
}
private async void _systemMediaTransportControls_ButtonPressed(SystemMediaTransportControls sender, SystemMediaTransportControlsButtonPressedEventArgs args)
@@ -814,6 +823,28 @@ private async void DanmuTimer_Tick(object sender, object e)
}
}
+ private void PositionTimer_Tick(object sender, object e)
+ {
+ if (!m_autoSkipOpEdFlag) return;
+ if (CurrentPlayItem == null) return;
+ if (CurrentPlayItem.EpisodeSkip == null) return;
+ SkipSection(CurrentPlayItem.EpisodeSkip.Op, "SkipOp", "自动跳过OP");
+ SkipSection(CurrentPlayItem.EpisodeSkip.Ed, "SkipEd", "自动跳过ED");
+ }
+
+ private void SkipSection(PlayerSkipItem section, string toastId, string message)
+ {
+ if (section == null) return;
+ if (!IsSectionValid(section) || (int)Player.Position != section.Start) return;
+ m_playerToastService.Show(toastId, message);
+ SetPosition(section.End);
+ }
+
+ private bool IsSectionValid(PlayerSkipItem section)
+ {
+ return section.Start != 0 && section.End != 0 && section.Start != section.End;
+ }
+
private async Task SetPlayItem(int index)
{
if (PlayInfos == null || PlayInfos.Count == 0)
@@ -1476,8 +1507,13 @@ private async Task GetPlayerInfo()
}
}
- TopOnline.Text = await playerHelper.GetOnline(CurrentPlayItem.avid, CurrentPlayItem.cid);
+ if (player_info.ViewPoints != null && player_info.ViewPoints.Any())
+ {
+ m_viewModel.ViewPoints = player_info.ViewPoints;
+ m_viewModel.ShowViewPointsBtn = true;
+ }
+ TopOnline.Text = await playerHelper.GetOnline(CurrentPlayItem.avid, CurrentPlayItem.cid);
}
public async Task ReportHistory(double progress = double.NaN)
@@ -1530,31 +1566,29 @@ private async Task ChangeQualityPlayVideo(BiliPlayUrlInfo qual
};
if (quality.PlayUrlType == BiliPlayUrlType.DASH)
{
- var audio = audioQuality == null ? quality.DashInfo.Audio : audioQuality.Audio;
- var video = quality.DashInfo.Video;
-
- result = await Player.PlayerDashUseNative(quality.DashInfo, quality.UserAgent, quality.Referer, positon: _postion);
+ var realPlayerType = (RealPlayerType)SettingService.GetValue(SettingConstants.Player.USE_REAL_PLAYER_TYPE, (int)SettingConstants.Player.DEFAULT_USE_REAL_PLAYER_TYPE);
+ if (realPlayerType==RealPlayerType.Native)
+ {
+ result = await Player.PlayerDashUseNative(quality.DashInfo, quality.UserAgent, quality.Referer, positon: _postion);
- if (!result.result)
+ if (!result.result)
+ {
+ result = await Player.PlayDashUseFFmpegInterop(quality.DashInfo, quality.UserAgent, quality.Referer,
+ positon: _postion);
+ }
+ }
+ else
{
- var mpd_url = new PlayerAPI().GenerateMPD(new Models.GenerateMPDModel()
+ result = await Player.PlayDashUseFFmpegInterop(quality.DashInfo, quality.UserAgent, quality.Referer,
+ positon: _postion);
+
+ if (!result.result)
{
- AudioBandwidth = audio.BandWidth.ToString(),
- AudioCodec = audio.Codecs,
- AudioID = audio.ID.ToString(),
- AudioUrl = audio.Url,
- Duration = quality.DashInfo.Duration,
- DurationMS = quality.Timelength,
- VideoBandwidth = video.BandWidth.ToString(),
- VideoCodec = video.Codecs,
- VideoID = video.ID.ToString(),
- VideoFrameRate = video.FrameRate.ToString(),
- VideoHeight = video.Height,
- VideoWidth = video.Width,
- VideoUrl = video.Url,
- });
- result = await Player.PlayDashUrlUseFFmpegInterop(mpd_url, quality.UserAgent, quality.Referer, positon: _postion);
+
+ result = await Player.PlayerDashUseNative(quality.DashInfo, quality.UserAgent, quality.Referer, positon: _postion);
+ }
}
+
}
else if (quality.PlayUrlType == BiliPlayUrlType.SingleFLV)
{
@@ -2546,6 +2580,11 @@ public async void Dispose()
danmuTimer.Stop();
danmuTimer = null;
}
+ if (m_positionTimer != null)
+ {
+ m_positionTimer.Stop();
+ m_positionTimer = null;
+ }
danmakuPool = null;
if (dispRequest != null)
{
@@ -2879,5 +2918,22 @@ private void Player_SizeChanged(object sender, SizeChangedEventArgs e)
// 更新画面比例
Player.SetRatioMode(PlayerSettingRatio.SelectedIndex);
}
+
+ private void TopBtnViewPoints_OnClick(object sender, RoutedEventArgs e)
+ {
+ m_viewModel.ShowViewPointsView = true;
+ }
+
+ private void ViewPointsGrid_OnTapped(object sender, TappedRoutedEventArgs e)
+ {
+ m_viewModel.ShowViewPointsView = false;
+ }
+
+ private void ViewPoint_OnTapped(object sender, TappedRoutedEventArgs e)
+ {
+ if (!(sender is FrameworkElement element)) return;
+ if (!(element.DataContext is PlayerInfoViewPoint viewPoint)) return;
+ SetPosition(viewPoint.From);
+ }
}
}
diff --git a/src/BiliLite.UWP/Controls/Settings/DownloadSettingsControl.xaml b/src/BiliLite.UWP/Controls/Settings/DownloadSettingsControl.xaml
index 80e269afd..c7cc63000 100644
--- a/src/BiliLite.UWP/Controls/Settings/DownloadSettingsControl.xaml
+++ b/src/BiliLite.UWP/Controls/Settings/DownloadSettingsControl.xaml
@@ -99,5 +99,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/BiliLite.UWP/Controls/Settings/DownloadSettingsControl.xaml.cs b/src/BiliLite.UWP/Controls/Settings/DownloadSettingsControl.xaml.cs
index 1e6530505..d049892dc 100644
--- a/src/BiliLite.UWP/Controls/Settings/DownloadSettingsControl.xaml.cs
+++ b/src/BiliLite.UWP/Controls/Settings/DownloadSettingsControl.xaml.cs
@@ -5,7 +5,6 @@
using Windows.UI.Xaml.Controls;
using BiliLite.Models.Common;
using BiliLite.Services;
-using BiliLite.ViewModels.Download;
using Microsoft.Extensions.DependencyInjection;
//https://go.microsoft.com/fwlink/?LinkId=234236 上介绍了“用户控件”项模板
@@ -14,11 +13,11 @@ namespace BiliLite.Controls.Settings
{
public sealed partial class DownloadSettingsControl : UserControl
{
- private readonly DownloadPageViewModel m_downloadPageViewModel;
+ private readonly DownloadService m_downloadService;
public DownloadSettingsControl()
{
- m_downloadPageViewModel = App.ServiceProvider.GetRequiredService();
+ m_downloadService = App.ServiceProvider.GetRequiredService();
this.InitializeComponent();
LoadDownlaod();
}
@@ -52,7 +51,7 @@ private void LoadDownlaod()
SettingService.SetValue(SettingConstants.Download.DOWNLOAD_PATH, folder.Path);
txtDownloadPath.Text = folder.Path;
Windows.Storage.AccessCache.StorageApplicationPermissions.FutureAccessList.Add(folder);
- m_downloadPageViewModel.RefreshDownloaded();
+ m_downloadService.RefreshDownloaded();
}
});
//旧版下载目录
@@ -89,14 +88,14 @@ private void LoadDownlaod()
swDownloadParallelDownload.Toggled += new RoutedEventHandler((e, args) =>
{
SettingService.SetValue(SettingConstants.Download.PARALLEL_DOWNLOAD, swDownloadParallelDownload.IsOn);
- m_downloadPageViewModel.UpdateSetting();
+ m_downloadService.UpdateSetting();
});
//付费网络下载
swDownloadAllowCostNetwork.IsOn = SettingService.GetValue(SettingConstants.Download.ALLOW_COST_NETWORK, false);
swDownloadAllowCostNetwork.Toggled += new RoutedEventHandler((e, args) =>
{
SettingService.SetValue(SettingConstants.Download.ALLOW_COST_NETWORK, swDownloadAllowCostNetwork.IsOn);
- m_downloadPageViewModel.UpdateSetting();
+ m_downloadService.UpdateSetting();
});
//下载完成发送通知
swDownloadSendToast.IsOn = SettingService.GetValue(SettingConstants.Download.SEND_TOAST, false);
@@ -104,6 +103,13 @@ private void LoadDownlaod()
{
SettingService.SetValue(SettingConstants.Download.SEND_TOAST, swDownloadSendToast.IsOn);
});
+ //使用下载索引
+ SwUseDownloadIndex.IsOn = SettingService.GetValue(SettingConstants.Download.USE_DOWNLOAD_INDEX,
+ SettingConstants.Download.DEFAULT_USE_DOWNLOAD_INDEX);
+ SwUseDownloadIndex.Toggled += (e, args) =>
+ {
+ SettingService.SetValue(SettingConstants.Download.USE_DOWNLOAD_INDEX, SwUseDownloadIndex.IsOn);
+ };
//下载类型
var selectedValue = (PlayUrlCodecMode)SettingService.GetValue(SettingConstants.Download.DEFAULT_VIDEO_TYPE, (int)DefaultVideoTypeOptions.DEFAULT_VIDEO_TYPE);
cbDownloadVideoType.SelectedItem = DefaultVideoTypeOptions.GetOption(selectedValue);
@@ -121,5 +127,11 @@ private void LoadDownlaod()
SettingService.SetValue(SettingConstants.Download.LOAD_OLD_DOWNLOAD, swDownloadLoadOld.IsOn);
});
}
+
+ private void BtnRebuildDownloadIndex_OnClick(object sender, RoutedEventArgs e)
+ {
+ m_downloadService.ClearIndex();
+ m_downloadService.LoadDownloaded(true);
+ }
}
}
diff --git a/src/BiliLite.UWP/Controls/Settings/PlaySettingsControl.xaml b/src/BiliLite.UWP/Controls/Settings/PlaySettingsControl.xaml
index 8f1af6eef..611e367ae 100644
--- a/src/BiliLite.UWP/Controls/Settings/PlaySettingsControl.xaml
+++ b/src/BiliLite.UWP/Controls/Settings/PlaySettingsControl.xaml
@@ -42,6 +42,18 @@
DisplayMemberPath="Name">
+
+
+
+
+
+
+
+