private async Task <IAttemptResult> EncodeVideosAsync(IWatchSession session, IDownloadContext context, IDownloadSettings settings, Action <string> onMessage, IEnumerable <string> segmentFilePaths, CancellationToken token) { var encodeSetting = new EncodeSettings() { FilePath = context.FileName, CommandFormat = settings.CommandFormat, TsFilePaths = segmentFilePaths, IsOverwriteEnable = settings.Overwrite, IsOverrideDTEnable = settings.OverrideVideoFileDateToUploadedDT, UploadedOn = session.Video !.DmcInfo.UploadedOn, IsNoEncodeEnable = settings.SaveWithoutEncode, }; try { await this._encorder.EncodeAsync(encodeSetting, onMessage, token); } catch (Exception e) { this._logger.Error($"ファイルの変換中にエラーが発生しました。({this.context!.GetLogContent()})", e); onMessage("動画の変換中にエラー発生"); return(AttemptResult.Fail($"ファイルの変換中にエラーが発生しました。(詳細: {e.Message})")); } return(AttemptResult.Succeeded()); }
private string GetFileName(IWatchSession session, IDownloadSettings settings) { string?economySuffix = session.Video !.DmcInfo.IsEnonomy ? settings.EconomySuffix : null; string?suffix = economySuffix; string ext = settings.SaveWithoutEncode ? FileFolder.TsFileExt : FileFolder.Mp4FileExt; string format = string.IsNullOrEmpty(settings.FileNameFormat) ? Format.DefaultFileNameFormat : settings.FileNameFormat; return(this._pathOrganizer.GetFilePath(format, session.Video !.DmcInfo, ext, settings.FolderPath, settings.IsReplaceStrictedEnable, settings.Overwrite, suffix)); }
private async Task <IAttemptResult <IStreamInfo> > GetStream(IWatchSession session, uint resolution) { IStreamInfo targetStream; try { IStreamsCollection streams = await session.GetAvailableStreamsAsync(); targetStream = streams.GetStream(resolution); } catch (Exception e) { this._logger.Error($"ストリームの取得に失敗しました。({this.context!.GetLogContent()})", e); return(AttemptResult <IStreamInfo> .Fail("ストリームの取得に失敗しました。", e)); } return(AttemptResult <IStreamInfo> .Succeeded(targetStream)); }
private async Task <IAttemptResult> EnsureSessionAsync(IWatchSession session, IDownloadSettings settings) { await session.EnsureSessionAsync(settings.NiconicoId); if (!session.IsSessionEnsured) { string message = session.State switch { WatchSessionState.HttpRequestOrPageAnalyzingFailure => "視聴ページの取得、または解析に失敗しました。", WatchSessionState.EncryptedVideo => "暗号化された動画のため、ダウンロードできません。", WatchSessionState.SessionEnsuringFailure => "セッションの確立に失敗しました。", _ => "不明なエラーにより、セッションの確立に失敗しました。" }; return(AttemptResult.Fail(message)); } else { this._logger.Log($"視聴セッションを確立しました。({this.context!.GetLogContent()})"); return(AttemptResult.Succeeded()); } }
/// <summary> /// 動画情報ファイルを保存する /// </summary> /// <param name="setting"></param> /// <param name="dmcInfo"></param> /// <returns></returns> public IAttemptResult DownloadVideoInfoAsync(IDownloadSettings setting, IWatchSession session, Action <string> onMessage) { if (session.Video is null) { return(AttemptResult.Fail("動画情報が未取得です。")); } onMessage($"動画情報の保存を開始します。"); this._logger.Log($"{session.Video.Id}の動画情報保存を開始"); string fileName = this._pathOrganizer.GetFilePath(setting.FileNameFormat, session.Video.DmcInfo, setting.VideoInfoExt, setting.FolderPath, setting.IsReplaceStrictedEnable, setting.Overwrite, setting.VideoInfoSuffix); var filePath = Path.Combine(setting.FolderPath, fileName); string content = setting.VideoInfoType switch { VideoInfoTypeSettings.Json => this._producer.GetJsonContent(session.Video.DmcInfo), VideoInfoTypeSettings.Xml => this._producer.GetXmlContent(session.Video.DmcInfo), _ => this._producer.GetContent(session.Video.DmcInfo), }; try { IOUtils.CreateDirectoryIfNotExist(fileName); this._fileIO.Write(filePath, content); } catch (Exception e) { onMessage("動画情報ファイルの書き込みに失敗しました。"); this._logger.Error("動画情報ファイルの書き込みに失敗しました。", e); return(AttemptResult.Fail($"動画情報ファイルの書き込みに失敗しました。(詳細:{e.Message})")); } onMessage($"動画情報ファイルを保存しました。"); return(AttemptResult.Succeeded()); }
public async Task <IAttemptResult> DownloadIchibaInfo(IWatchSession session, IDownloadSettings settings, Action <string> onMessage, IDownloadContext context) { if (session.Video is null) { return(new AttemptResult() { Message = "セッション情報のVideoがnullです。" }); } onMessage($"市場APIへのアクセスを開始します。({session.Video.Id})"); var getResult = await this._niconicoIchibaHandler.GetIchibaInfo(session.Video.Id); if (!getResult.IsSucceeded || getResult.Data is null) { onMessage($"市場APIからの情報取得に失敗しました。({session.Video.Id})"); if (getResult.Exception is not null) { this._logger.Error($"市場情報の取得に失敗しました。(詳細:{getResult.Message} ,{context.GetLogContent()})", getResult.Exception); } else { this._logger.Error($"市場情報の取得に失敗しました。(詳細:{getResult.Message} ,{context.GetLogContent()})"); } return(new AttemptResult() { Message = getResult.Message }); } onMessage($"市場APIからの情報取得を取得しました。({session.Video.Id})"); string content; if (settings.IchibaInfoType != IchibaInfoTypeSettings.Html) { try { content = this.GetContent(getResult.Data, settings.IchibaInfoType == IchibaInfoTypeSettings.Xml); } catch (Exception e) { this._logger.Error($"市場情報のシリアル化に失敗しました。(詳細:{getResult.Message} ,{context.GetLogContent()})", e); onMessage($"市場情報のシリアル化に失敗しました。({session.Video.Id})"); return(new AttemptResult() { Message = "市場情報のシリアル化に失敗しました。" }); } } else { try { content = this.GetHtmlContent(getResult.Data, session.Video.Id); } catch (Exception e) { this._logger.Error($"市場情報のシリアル化に失敗しました。(詳細:{getResult.Message} ,{context.GetLogContent()})", e); onMessage($"市場情報のシリアル化に失敗しました。({session.Video.Id})"); return(new AttemptResult() { Message = "市場情報のシリアル化に失敗しました。" }); } } string filePath = this._path.GetFilePath(settings.FileNameFormat, session.Video !.DmcInfo, settings.IchibaInfoExt, settings.FolderPath, settings.IsReplaceStrictedEnable, settings.Overwrite, settings.IchibaInfoSuffix); try { this._fileIO.Write(filePath, content); } catch (Exception e) { this._logger.Error($"市場情報ファイルの書き込みに失敗しました。({context.GetLogContent()})", e); onMessage($"市場情報ファイルの書き込みに失敗しました。({session.Video.Id})"); return(new AttemptResult() { Message = $"市場情報ファイルの書き込みに失敗しました。(詳細:{e.Message})" }); } onMessage($"市場情報ファイルの保存が完了しました。({session.Video.Id})"); return(new AttemptResult() { IsSucceeded = true }); }
/// <summary> /// 市場情報をダウンロードする /// </summary> private async Task <IAttemptResult> DownloadIchibaInfoAsync(IDownloadSettings settings, IWatchSession session, Action <string> onMessage, IDownloadContext context) { var iDownloader = DIFactory.Provider.GetRequiredService <IIchibaInfoDownloader>(); IAttemptResult result; try { result = await iDownloader.DownloadIchibaInfo(session, settings, onMessage, context); } catch (Exception e) { this.logger.Error("市場情報のダウンロードに失敗しました。", e); return(AttemptResult.Fail($"市場情報のダウンロードに失敗しました。({e.Message})")); } return(result); }
/// <summary> /// コメントをダウンロードする /// </summary> private async Task <IAttemptResult> TryDownloadCommentAsync(IDownloadSettings settings, IWatchSession session, Action <string> onMessage, IDownloadContext context, CancellationToken token) { Cdl::ICommentDownloader? v1 = null; V2Comment::ICommentDownloader?v2 = null; if (settings.EnableExperimentalCommentSafetySystem) { v2 = DIFactory.Provider.GetRequiredService <V2Comment::ICommentDownloader>(); } else { v1 = DIFactory.Provider.GetRequiredService <Cdl::ICommentDownloader>(); } IAttemptResult result; try { result = v2 is null ? await v1 !.DownloadComment(session, settings, onMessage, context, token) : await v2.DownloadCommentAsync(session.Video !.DmcInfo, settings, context, token); } catch (Exception e) { this.logger.Error("コメントのダウンロードに失敗しました。", e); return(AttemptResult.Fail($"コメントのダウンロードに失敗しました。({e.Message})")); } return(result); }
/// <summary> /// サムネイルをダウンロードする /// </summary> private async Task <IAttemptResult> TryDownloadThumbAsync(IDownloadSettings setting, IWatchSession session) { var thumbDownloader = DIFactory.Provider.GetRequiredService <Tdl::IThumbDownloader>(); IAttemptResult result; try { result = await thumbDownloader.DownloadThumbnailAsync(setting, session); } catch (Exception e) { this.logger.Error($"サムネイルのダウンロードに失敗しました。", e); return(AttemptResult.Fail($"サムネイルのダウンロードに失敗しました。(詳細:{e.Message})")); } return(result); }
/// <summary> /// 動画情報をダウンロードする /// </summary> private IAttemptResult TryDownloadDescriptionAsync(IDownloadSettings settings, IWatchSession session, Action <string> onMessage) { var descriptionDownloader = DIFactory.Provider.GetRequiredService <DDL::IDescriptionDownloader>(); IAttemptResult result; try { result = descriptionDownloader.DownloadVideoInfoAsync(settings, session, onMessage); } catch (Exception e) { this.logger.Error($"動画情報のダウンロードに失敗しました。", e); return(AttemptResult.Fail($"動画情報のダウンロードに失敗しました。(詳細:{e.Message})")); } return(result); }
/// <summary> /// 非同期で動画をダウンロードする /// </summary> private async Task <IAttemptResult> TryDownloadVideoAsync(IDownloadSettings settings, Action <string> onMessage, IWatchSession session, IDownloadContext context, CancellationToken token) { var videoDownloader = DIFactory.Provider.GetRequiredService <Vdl::IVideoDownloader>(); IAttemptResult result; try { result = await videoDownloader.DownloadVideoAsync(settings, onMessage, context, session, token); } catch (Exception e) { this.logger.Error($"動画のダウンロードに失敗しました。({context.GetLogContent()})", e); return(AttemptResult.Fail($"動画のダウンロードに失敗しました。(詳細:{e.Message})")); } return(result); }
public async Task <IAttemptResult> DownloadComment(IWatchSession session, IDownloadSettings settings, Action <string> onMessage, IDownloadContext context, CancellationToken token) { if (session.Video is null) { return(AttemptResult.Fail("動画情報が未取得です。")); } string filePath = this._pathOrganizer.GetFilePath(settings.FileNameFormat, session.Video !.DmcInfo, ".xml", settings.FolderPath, settings.IsReplaceStrictedEnable, settings.Overwrite); string ownerFileName = this._pathOrganizer.GetFilePath(settings.FileNameFormat, session.Video !.DmcInfo, ".xml", settings.FolderPath, settings.IsReplaceStrictedEnable, settings.Overwrite, settings.OwnerComSuffix); if (token.IsCancellationRequested) { return(this.GetCancelledResult()); } onMessage("コメントのダウンロードを開始します。"); this._logger.Log($"{settings.NiconicoId}のコメントダウンロードを開始します。({context.GetLogContent()})"); ICommentCollection result; try { result = await this._client.DownloadCommentAsync(session.Video !.DmcInfo, settings, onMessage, context, token); } catch (Exception e) { this._logger.Error($"コメントの取得に失敗しました。({context.GetLogContent()})", e); return(AttemptResult.Fail($"コメントの取得に失敗しました。(詳細:{e.Message})")); } onMessage("コメントのダウンロードが完了しました。"); if (token.IsCancellationRequested) { return(this.GetCancelledResult()); } onMessage("コメントの変換処理を開始します。"); IStoreCommentsData data; try { data = this._commentConverter.ConvertToStoreCommentsData(result, settings); } catch (Exception e) { this._logger.Error($"コメントの解析に失敗しました。({context.GetLogContent()})", e); return(AttemptResult.Fail($"コメントの解析に失敗しました。")); } onMessage("コメントの変換処理が完了しました。"); data.FilePath = filePath; data.OwnerFilPath = ownerFileName; if (token.IsCancellationRequested) { return(this.GetCancelledResult()); } onMessage($"コメントの書き込みを開始します。"); try { this._commentStream.Write(data, settings.Overwrite); } catch (Exception e) { this._logger.Error($"コメントの書き込みに失敗しました。({context.GetLogContent()})", e); return(AttemptResult.Fail("コメントの書き込みに失敗しました。")); } onMessage("コメントのダウンロードが完了しました。"); this._logger.Log($"コメントのダウンロードが完了しました。({context.GetLogContent()})"); return(AttemptResult.Succeeded()); }
public async Task <IAttemptResult> DownloadVideoAsync(IDownloadSettings settings, Action <string> onMessage, IDownloadContext context, IWatchSession session, CancellationToken token) { IAttemptResult OnCanceled() { this._logger.Log($"ユーザーの操作によって動画のダウンロード処理がキャンセルされました。({context.GetLogContent()})"); onMessage("ダウンロードをキャンセル"); return(AttemptResult.Fail("処理がキャンセルされました")); } this.context = context; this._logger.Log($"動画のダウンロードを開始しました。({context.GetLogContent()})"); if (session.IsSessionExipired) { this._logger.Log($"セッションが失効していたため動画のダウンロードをキャンセルします。({context.GetLogContent()})"); return(AttemptResult <string> .Fail("セッションが失効済のためダウンロード出来ません。")); } if (!session.IsSessionEnsured) { if (token.IsCancellationRequested) { return(OnCanceled()); } IAttemptResult sessionR = await this.EnsureSessionAsync(session, settings); if (!sessionR.IsSucceeded) { onMessage(sessionR.Message ?? ""); return(sessionR); } } //ファイル名取得 string fileName = this.GetFileName(session, settings); context.FileName = fileName; if (token.IsCancellationRequested) { return(OnCanceled()); } //ストリーム系 IAttemptResult <IStreamInfo> streamResult = await this.GetStream(session, settings.VerticalResolution); if (!streamResult.IsSucceeded || streamResult.Data is null) { return(AttemptResult.Fail(streamResult.Message, streamResult.Exception)); } IStreamInfo targetStream = streamResult.Data; List <string> rawsegmentFilePaths = targetStream.StreamUrls.Select(u => u.FileName).ToList(); context.ActualVerticalResolution = targetStream.Resolution?.Vertical ?? 0; context.OriginalSegmentsCount = targetStream.StreamUrls.Count; if (token.IsCancellationRequested) { return(OnCanceled()); } //レジューム系 string segmentDirectoryName; IAttemptResult <string> sResult = settings.ResumeEnable ? this.GetAndSetSegmentsDirectoryInfoIfExists(settings.NiconicoId, targetStream.Resolution?.Vertical ?? 0, targetStream) : AttemptResult <string> .Fail(); if (sResult.IsSucceeded && sResult.Data is not null) { segmentDirectoryName = sResult.Data; onMessage("DLをレジューム"); this._logger.Log($"ダウンロードをレジュームします。({context.GetLogContent()})"); } else { segmentDirectoryName = $"{settings.NiconicoId}-{targetStream.Resolution?.Vertical ?? 0}-{DateTime.Now.ToString("yyyy-MM-dd")}"; } List <string> segmentFilePaths = rawsegmentFilePaths.Select(p => Path.Combine(AppContext.BaseDirectory, "tmp", segmentDirectoryName, p)).ToList(); //DL系 IAttemptResult downloadresult = await this.DownloadVideoInternalAsync(targetStream, onMessage, context, settings.MaxParallelSegmentDLCount, segmentDirectoryName, token); if (!downloadresult.IsSucceeded) { return(downloadresult); } if (token.IsCancellationRequested) { return(OnCanceled()); } onMessage("動画を変換中..."); IAttemptResult encodeResult = await this.EncodeVideosAsync(session, context, settings, onMessage, segmentFilePaths, token); if (!encodeResult.IsSucceeded) { return(encodeResult); } onMessage("動画の変換が完了"); this.DeleteTmpFolder(segmentDirectoryName, onMessage); bool isEconomy = session.Video !.DmcInfo.IsEnonomy; if (settings.IsEconomy && settings.DeleteExistingEconomyFile && !isEconomy) { this.RemoveEconomyFile(settings.FilePath); } this._fileStorehandler.Add(settings.NiconicoId, Path.Combine(settings.FolderPath, fileName)); this._logger.Log($"動画のダウンロードが完了しました。({context.GetLogContent()})"); return(AttemptResult.Succeeded()); }
public async Task <IAttemptResult> DownloadThumbnailAsync(IDownloadSettings settings, IWatchSession session) { if (session.Video is null) { return(AttemptResult.Fail("動画情報が未取得です。")); } var filepath = this._pathOrganizer.GetFilePath(settings.FileNameFormat, session.Video !.DmcInfo, settings.ThumbnailExt, settings.FolderPath, settings.IsReplaceStrictedEnable, settings.Overwrite, settings.ThumbSuffix); string?thumbUrl; try { thumbUrl = session.Video !.DmcInfo.ThumbInfo.GetSpecifiedThumbnail(settings.ThumbSize); } catch (Exception e) { this._logger.Error($"サムネイルURLの取得に失敗しました。", e); return(AttemptResult.Fail("サムネイルのURLを取得できませんでした。")); } byte[] data; try { data = await this.DownloadAsync(thumbUrl); } catch (Exception e) { this._logger.Error($"サムネイルの取得に失敗しました。", e); return(AttemptResult.Fail($"サムネイルの取得に失敗しました。(詳細: {e.Message})")); } try { this.WriteThumb(data, filepath); } catch (Exception e) { this._logger.Error($"サムネイルの保存に失敗しました。", e); return(AttemptResult.Fail($"サムネイルの保存に失敗しました。(詳細: {e.Message})")); } return(AttemptResult.Succeeded()); }