/// <summary> /// 動画ストリームの取得します /// 他にダウンロードされているアイテムは強制的に一時停止し、再生終了後に再開されます /// </summary> /// <exception cref="NotSupportedException" /> public async Task <IVideoStreamingSession> CreateVideoStreamingSession(NicoVideoQuality quality, bool forceDownload = false) { // オンラインの場合は削除済みかを確認する object watchRes = null; if (Helpers.InternetConnection.IsInternet()) { // 動画視聴ページへアクセス // 動画再生準備およびコメント取得準備が行われる watchRes = await VisitWatchPage(quality); // 動画情報ページアクセスだけでも内部の動画情報データは更新される var videoInfo = Database.NicoVideoDb.Get(RawVideoId); // 動作互換性のためにサムネから拾うように戻す? // var videoInfo = await _ContentProvider.GetNicoVideoInfo(RawVideoId); if (videoInfo.IsDeleted) { // ニコニコサーバー側で動画削除済みの場合は再生不可 // (NiconnicoContentProvider側で動画削除動作を実施している) throw new NotSupportedException($"動画は {videoInfo.PrivateReasonType.ToCulturelizeString()} のため視聴できません"); } } if (!forceDownload) { // キャッシュ済みアイテムを問い合わせ var cacheRequests = await CacheManager.GetCacheRequest(RawVideoId); NicoVideoCacheRequest playCandidateRequest = null; var req = cacheRequests.FirstOrDefault(x => x.Quality == quality); if (req is NicoVideoCacheInfo || req is NicoVideoCacheProgress) { playCandidateRequest = req; } if (req == null) { var playableReq = cacheRequests.Where(x => x is NicoVideoCacheInfo || x is NicoVideoCacheProgress); if (playableReq.Any()) { // 画質指定がない、または指定画質のキャッシュがない場合には // キャッシュが存在する画質(高画質優先)を取り出す playCandidateRequest = playableReq.OrderBy(x => x.Quality).FirstOrDefault(); } } if (playCandidateRequest is NicoVideoCacheInfo) { var playCandidateCache = playCandidateRequest as NicoVideoCacheInfo; try { var file = await StorageFile.GetFileFromPathAsync(playCandidateCache.FilePath); return(new LocalVideoStreamingSession(file, playCandidateCache.Quality, _Context)); } catch { Debug.WriteLine("動画視聴時にキャッシュが見つかったが、キャッシュファイルを利用した再生セッションの作成に失敗、オンライン再生を試行します"); } } else if (playCandidateRequest is NicoVideoCacheProgress) { /* * if (Helpers.ApiContractHelper.IsFallCreatorsUpdateAvailable) * { * var playCandidateCacheProgress = playCandidateRequest as NicoVideoCacheProgress; * var op = playCandidateCacheProgress.DownloadOperation; * var refStream = op.GetResultRandomAccessStreamReference(); * return new DownloadProgressVideoStreamingSession(refStream, playCandidateCacheProgress.Quality); * } */ } } // キャッシュがない場合はオンラインで再生 if (watchRes is WatchApiResponse) { var res = watchRes as WatchApiResponse; if (res.flashvars.movie_type == "swf") { throw new NotSupportedException("SWF形式の動画はサポートしていません"); } if (res.VideoUrl.OriginalString.StartsWith("rtmp")) { throw new NotSupportedException("RTMP形式の動画はサポートしていません"); } if (res.IsDeleted) { throw new NotSupportedException("動画は削除されています"); } return(new SmileVideoStreamingSession( res.VideoUrl, _Context )); } else if (watchRes is DmcWatchData) { var res = watchRes as DmcWatchData; if (res.DmcWatchResponse.Video.IsDeleted) { throw new NotSupportedException("動画は削除されています"); } if (res.DmcWatchResponse.Video.DmcInfo != null) { if (res.DmcWatchResponse.Video?.DmcInfo?.Quality == null) { throw new NotSupportedException("動画の視聴権がありません"); } if (quality.IsLegacy() && res.DmcWatchResponse.Video.SmileInfo != null) { return(new SmileVideoStreamingSession( new Uri(res.DmcWatchResponse.Video.SmileInfo.Url), _Context )); } else { return(new DmcVideoStreamingSession( res, quality.IsDmc() ? quality : NicoVideoQuality.Dmc_High, _Context )); } } else if (res.DmcWatchResponse.Video.SmileInfo != null) { return(new SmileVideoStreamingSession( new Uri(res.DmcWatchResponse.Video.SmileInfo.Url), _Context )); } else { throw new NotSupportedException("動画ページ情報から動画ファイルURLを検出できませんでした"); } } else { throw new NotSupportedException("動画の再生準備に失敗(動画ページの解析でエラーが発生)"); } }
public async Task <object> VisitWatchPage(NicoVideoQuality quality) { if (!Helpers.InternetConnection.IsInternet()) { return(null); } object res = null; try { if (quality.IsLegacy()) { res = await GetWatchApiResponse(IsForceSmileLowQuality); } else { var dmcRes = await GetDmcWatchResponse(); res = dmcRes; } } catch { if (quality.IsLegacy()) { throw; } await Task.Delay(TimeSpan.FromSeconds(1)); res = await GetWatchApiResponse(IsForceSmileLowQuality); } _LastAccessResponse = res; if (res is WatchApiResponse) { var watchApiRes = res as WatchApiResponse; CommentClient = new CommentClient(_Context, new CommentServerInfo() { ServerUrl = watchApiRes.CommentServerUrl.OriginalString, VideoId = RawVideoId, DefaultThreadId = (int)watchApiRes.ThreadId, CommunityThreadId = (int)watchApiRes.OptionalThreadId, ViewerUserId = watchApiRes.viewerInfo.id, ThreadKeyRequired = watchApiRes.IsKeyRequired }); return(res); } else if (res is DmcWatchData) { var watchdata = res as DmcWatchData; var dmcRes = watchdata.DmcWatchResponse; CommentClient = new CommentClient(_Context, new CommentServerInfo() { ServerUrl = dmcRes.Thread.ServerUrl, VideoId = RawVideoId, DefaultThreadId = int.Parse(dmcRes.Thread.Ids.Default), ViewerUserId = dmcRes.Viewer.Id, ThreadKeyRequired = dmcRes.Video.IsOfficial }) { LastAccessDmcWatchResponse = dmcRes }; if (int.TryParse(dmcRes.Thread.Ids.Community, out var communityThreadId)) { CommentClient.CommentServerInfo.CommunityThreadId = communityThreadId; Debug.WriteLine("dmcRes.Video.DmcInfo.Thread.PostkeyAvailable: " + dmcRes.Video.DmcInfo?.Thread?.PostkeyAvailable); } return(res); } else { return(null); } }