using DownKyi.Core.BiliApi.BiliUtils; using DownKyi.Core.BiliApi.VideoStream; using DownKyi.Core.BiliApi.Zone; using DownKyi.Core.FileName; using DownKyi.Core.Logging; using DownKyi.Core.Settings; using DownKyi.Core.Settings.Models; using DownKyi.Core.Utils; using DownKyi.Events; using DownKyi.Models; using DownKyi.Utils; using DownKyi.ViewModels.Dialogs; using DownKyi.ViewModels.DownloadManager; using DownKyi.ViewModels.PageViewModels; using Prism.Events; using Prism.Services.Dialogs; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading; namespace DownKyi.Services.Download { /// /// 添加到下载列表服务 /// public class AddToDownloadService { private readonly string Tag = "AddToDownloadService"; private IInfoService videoInfoService; private VideoInfoView videoInfoView; private List videoSections; // 下载内容 private bool downloadAudio = true; private bool downloadVideo = true; private bool downloadDanmaku = true; private bool downloadSubtitle = true; private bool downloadCover = true; /// /// 添加下载 /// /// public AddToDownloadService(PlayStreamType streamType) { switch (streamType) { case PlayStreamType.VIDEO: videoInfoService = new VideoInfoService(null); break; case PlayStreamType.BANGUMI: videoInfoService = new BangumiInfoService(null); break; case PlayStreamType.CHEESE: videoInfoService = new CheeseInfoService(null); break; default: break; } } /// /// 添加下载 /// /// /// public AddToDownloadService(string id, PlayStreamType streamType) { switch (streamType) { case PlayStreamType.VIDEO: videoInfoService = new VideoInfoService(id); break; case PlayStreamType.BANGUMI: videoInfoService = new BangumiInfoService(id); break; case PlayStreamType.CHEESE: videoInfoService = new CheeseInfoService(id); break; default: break; } } public void SetVideoInfoService(IInfoService videoInfoService) { this.videoInfoService = videoInfoService; } public void GetVideo(VideoInfoView videoInfoView, List videoSections) { this.videoInfoView = videoInfoView; this.videoSections = videoSections; } public void GetVideo() { videoInfoView = videoInfoService.GetVideoView(); if (videoInfoView == null) { LogManager.Debug(Tag, "VideoInfoView is null."); return; } videoSections = videoInfoService.GetVideoSections(true); if (videoSections == null) { LogManager.Debug(Tag, "videoSections is not exist."); videoSections = new List { new VideoSection { Id = 0, Title = "default", IsSelected = true, VideoPages = videoInfoService.GetVideoPages() } }; } // 将所有视频设置为选中 foreach (VideoSection section in videoSections) { foreach (var item in section.VideoPages) { item.IsSelected = true; } } } /// /// 解析视频流 /// /// public void ParseVideo(IInfoService videoInfoService) { if (videoSections == null) { return; } foreach (VideoSection section in videoSections) { foreach (VideoPage page in section.VideoPages) { // 执行解析任务 videoInfoService.GetVideoStream(page); } } } /// /// 选择文件夹和下载项 /// /// public string SetDirectory(IDialogService dialogService) { // 选择的下载文件夹 string directory = string.Empty; // 是否使用默认下载目录 if (SettingsManager.GetInstance().IsUseSaveVideoRootPath() == AllowStatus.YES) { // 下载内容 VideoContentSettings videoContent = SettingsManager.GetInstance().GetVideoContent(); downloadAudio = videoContent.DownloadAudio; downloadVideo = videoContent.DownloadVideo; downloadDanmaku = videoContent.DownloadDanmaku; downloadSubtitle = videoContent.DownloadSubtitle; downloadCover = videoContent.DownloadCover; directory = SettingsManager.GetInstance().GetSaveVideoRootPath(); } else { // 打开文件夹选择器 dialogService.ShowDialog(ViewDownloadSetterViewModel.Tag, null, result => { if (result.Result == ButtonResult.OK) { // 选择的下载文件夹 directory = result.Parameters.GetValue("directory"); // 下载内容 downloadAudio = result.Parameters.GetValue("downloadAudio"); downloadVideo = result.Parameters.GetValue("downloadVideo"); downloadDanmaku = result.Parameters.GetValue("downloadDanmaku"); downloadSubtitle = result.Parameters.GetValue("downloadSubtitle"); downloadCover = result.Parameters.GetValue("downloadCover"); } }); } if (!Directory.Exists(Directory.GetDirectoryRoot(directory))) { var alert = new AlertService(dialogService); alert.ShowError(DictionaryResource.GetString("DriveNotFound")); directory = string.Empty; } // 下载设置dialog中如果点击取消或者关闭窗口, // 会返回空字符串, // 这时直接退出 if (directory == null || directory == string.Empty) { return null; } // 文件夹不存在则创建 if (!Directory.Exists(directory)) { Directory.CreateDirectory(directory); } return directory; } /// /// 添加到下载列表 /// /// 传递事件的对象 /// 下载路径 /// 是否下载所有,包括未选中项 /// 添加的数量 public int AddToDownload(IEventAggregator eventAggregator, string directory, bool isAll = false) { if (directory == null || directory == string.Empty) { return -1; } if (videoSections == null) { return -1; } // 视频计数 int i = 0; // 添加到下载 foreach (VideoSection section in videoSections) { if (section.VideoPages == null) { continue; } foreach (VideoPage page in section.VideoPages) { // 只下载选中项,跳过未选中项 if (!isAll && !page.IsSelected) { continue; } // 没有解析的也跳过 if (page.PlayUrl == null) { continue; } // 判断VideoQuality int retry = 0; while (page.VideoQuality == null && retry < 5) { // 执行解析任务 videoInfoService.GetVideoStream(page); retry++; } if (page.VideoQuality == null) { continue; } // 判断是否同一个视频,需要cid、画质、音质、视频编码都相同 // 如果存在正在下载列表,则跳过,并提示 bool isDownloading = false; foreach (DownloadingItem item in App.DownloadingList) { if (item.DownloadBase == null) { continue; } if (item.DownloadBase.Cid == page.Cid && item.Resolution.Id == page.VideoQuality.Quality && item.AudioCodec.Name == page.AudioQualityFormat && item.VideoCodecName == page.VideoQuality.SelectedVideoCodec) { eventAggregator.GetEvent().Publish($"{page.Name}{DictionaryResource.GetString("TipAlreadyToAddDownloading")}"); isDownloading = true; break; } } if (isDownloading) { continue; } // TODO 如果存在下载完成列表,弹出选择框是否再次下载 bool isDownloaded = false; foreach (DownloadedItem item in App.DownloadedList) { if (item.DownloadBase == null) { continue; } if (item.DownloadBase.Cid == page.Cid && item.Resolution.Id == page.VideoQuality.Quality && item.AudioCodec.Name == page.AudioQualityFormat && item.VideoCodecName == page.VideoQuality.SelectedVideoCodec) { eventAggregator.GetEvent().Publish($"{page.Name}{DictionaryResource.GetString("TipAlreadyToAddDownloaded")}"); isDownloaded = true; break; } } if (isDownloaded) { continue; } // 视频分区 int zoneId = -1; List zoneList = VideoZone.Instance().GetZones(); ZoneAttr zone = zoneList.Find(it => it.Id == videoInfoView.TypeId); if (zone != null) { if (zone.ParentId == 0) { zoneId = zone.Id; } else { ZoneAttr zoneParent = zoneList.Find(it => it.Id == zone.ParentId); if (zoneParent != null) { zoneId = zoneParent.Id; } } } // 如果只有一个视频章节,则不在命名中出现 string sectionName = string.Empty; if (videoSections.Count > 1) { sectionName = section.Title; } // 文件路径 List fileNameParts = SettingsManager.GetInstance().GetFileNameParts(); FileName fileName = FileName.Builder(fileNameParts) .SetSection(Format.FormatFileName(sectionName)) .SetMainTitle(Format.FormatFileName(videoInfoView.Title)) .SetPageTitle(Format.FormatFileName(page.Name)) .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" : page.VideoQuality.SelectedVideoCodec.Contains("Dolby") ? "Dolby Vision" : page.VideoQuality.SelectedVideoCodec.Contains("AV1") ? "AV1" : "") .SetVideoPublishTime(page.PublishTime) .SetAvid(page.Avid) .SetBvid(page.Bvid) .SetCid(page.Cid) .SetUpMid(page.Owner.Mid) .SetUpName(Format.FormatFileName(page.Owner.Name)); // 序号设置 OrderFormat orderFormat = SettingsManager.GetInstance().GetOrderFormat(); switch (orderFormat) { case OrderFormat.NATURAL: fileName.SetOrder(page.Order); break; case OrderFormat.LEADING_ZEROS: fileName.SetOrder(page.Order, section.VideoPages.Count); break; } // 合成绝对路径 string filePath = Path.Combine(directory, fileName.RelativePath()); // 视频类别 PlayStreamType playStreamType; switch (videoInfoView.TypeId) { case -10: playStreamType = PlayStreamType.CHEESE; break; case 13: case 23: case 177: case 167: case 11: playStreamType = PlayStreamType.BANGUMI; break; case 1: case 3: case 129: case 4: case 36: case 188: case 234: case 223: case 160: case 211: case 217: case 119: case 155: case 202: case 5: case 181: default: playStreamType = PlayStreamType.VIDEO; break; } // 添加到下载列表 App.PropertyChangeAsync(new Action(() => { // 如果不存在,直接添加到下载列表 DownloadBase downloadBase = new DownloadBase { Bvid = page.Bvid, Avid = page.Avid, Cid = page.Cid, EpisodeId = page.EpisodeId, CoverUrl = videoInfoView.CoverUrl, PageCoverUrl = page.FirstFrame, ZoneId = zoneId, FilePath = filePath, Order = page.Order, MainTitle = videoInfoView.Title, Name = page.Name, Duration = page.Duration, VideoCodecName = page.VideoQuality.SelectedVideoCodec, Resolution = new Quality { Name = page.VideoQuality.QualityFormat, Id = page.VideoQuality.Quality }, AudioCodec = Constant.GetAudioQualities().FirstOrDefault(t => { return t.Name == page.AudioQualityFormat; }), }; Downloading downloading = new Downloading { PlayStreamType = playStreamType, DownloadStatus = DownloadStatus.NOT_STARTED, }; // 需要下载的内容 downloadBase.NeedDownloadContent["downloadAudio"] = downloadAudio; downloadBase.NeedDownloadContent["downloadVideo"] = downloadVideo; downloadBase.NeedDownloadContent["downloadDanmaku"] = downloadDanmaku; downloadBase.NeedDownloadContent["downloadSubtitle"] = downloadSubtitle; downloadBase.NeedDownloadContent["downloadCover"] = downloadCover; DownloadingItem downloadingItem = new DownloadingItem { DownloadBase = downloadBase, Downloading = downloading, PlayUrl = page.PlayUrl, }; App.DownloadingList.Add(downloadingItem); Thread.Sleep(10); })); i++; } } return i; } } }