public void ViewModelFactoryBaseService_CreatePlaylistVideoVM() { var model = new PlaylistVideo(new MediaFile()); var vm = factoryService.CreateViewModel <PlaylistElementVM, IPlaylistElement> (model); Assert.IsTrue(vm is PlaylistVideoVM); }
void HandleInsertVideoInPlaylist(InsertVideoInPlaylistEvent e) { MediaFile file = App.Current.Dialogs.OpenMediaFile(); if (file != null) { PlaylistVideo video = new PlaylistVideo(file); InsertPlaylistElements(video, e.Position); } }
public MusicItem(PlaylistVideo Video) { Title = Video.Title; Thumbnail = Video.Thumbnails.GetMaxResUrl(); Author = Video.Author.ChannelTitle; UrlOrId = Video.Id; Duration = Video.Duration ?? TimeSpan.Zero; PublicUrl = Video.Url; IsYouTube = true; }
public YoutubeTrack(PlaylistVideo video, YoutubeClient yC, HttpClient hC) { this.playlistVideo = video; this.Location = new Uri(video.Url); this.Title = video.Title; this.Artist = video.Author; this.Duration = video.Duration; this.hostHttpClient = hC; this.hostYoutubeClient = yC; this.MetadataLoaded = true; }
void LoadVideo(PlaylistVideo video) { loadedPlaylistElement = video; MediaFileSet fileSet = new MediaFileSet(); fileSet.Add(video.File); EmitLoadDrawings(null); UpdateCamerasConfig(new List <CameraConfig> { new CameraConfig(0) }, null); InternalOpen(fileSet, false, true, true); }
public void TestClone_CloneIgnore_PlaylistVideo() { var playlistVideo = new PlaylistVideo(new MediaFile()); playlistVideo.File.Name = "Test1"; var playlistVideo2 = playlistVideo.Clone(); Assert.AreEqual(playlistVideo.File.Name, playlistVideo2.File.Name); playlistVideo.File.Name = "Test2"; playlistVideo2 = playlistVideo.Clone(); Assert.AreEqual(playlistVideo.File.Name, playlistVideo2.File.Name); }
public JsonResult Insert(PlaylistVideo playVideo) { bool exist = playlistVideoService.SongExistOrNot(playVideo); if (exist == true) { return(Json(exist, JsonRequestBehavior.AllowGet)); } else { playlistVideoService.Insert(playVideo); return(Json(exist, JsonRequestBehavior.AllowGet)); } }
void AddVideo(IPlaylistElement element, bool prepend) { MediaFile file = Helpers.Misc.OpenFile(widget); if (file != null) { PlaylistVideo video = new PlaylistVideo(file); int index = playlist.Elements.IndexOf(element); if (!prepend) { index++; } playlist.Elements.Insert(index, video); } }
void AddVideo(Playlist playlist, IPlaylistElement element, bool prepend, TreeIter parent) { MediaFile file = LongoMatch.Gui.Helpers.Misc.OpenFile(this); if (file != null) { PlaylistVideo video = new PlaylistVideo(file); int index = playlist.Elements.IndexOf(element); if (!prepend) { index++; } playlist.Elements.Insert(index, video); (Model as TreeStore).InsertWithValues(parent, index, video); } }
void LoadConversionJob(ConversionJob job) { videoEditor = App.Current.MultimediaToolkit.GetVideoEditor(); videoEditor.EncodingSettings = job.EncodingSettings; videoEditor.Progress += OnProgress; videoEditor.Error += OnError; foreach (MediaFile file in job.InputFiles) { PlaylistVideo video = new PlaylistVideo(file); Log.Debug("Convert video " + video.File.FilePath); videoEditor.AddSegment(video.File.FilePath, 0, -1, 1, "", video.File.HasAudio, new Area()); } videoEditor.Start(); }
public void Initialize() { video = new Video { Id = 1, Name = "Bailando", Author = "Mauro", Hour = 1, MinSeconds = 2.10, LinkVideo = "www.youtube.com/videomauro", CategoryVideo = new List <CategoryVideo>(), PlaylistVideo = new List <PlaylistVideo>() }; category = new Category { Id = 1, Name = "Musica", CategoryTrack = new List <CategoryTrack>(), }; categoryVideo = new CategoryVideo { IdCategory = category.Id, Category = category, IdVideo = video.Id, Video = video, }; playlist = new Playlist { Id = 1, Name = "Musica para Mauro", Description = "Variado pop, rock, etc", Image = "", PlaylistTrack = new List <PlaylistTrack>() }; playlistVideo = new PlaylistVideo { IdPlaylist = playlist.Id, Playlist = playlist, IdVideo = video.Id, Video = video }; video.PlaylistVideo.Add(playlistVideo); video.CategoryVideo.Add(categoryVideo); }
public void Initialize() { playlistVideo = new PlaylistVideo(); playlist = new Playlist { Name = "Cumbia", Id = 1, Description = "Boliche", Image = "" }; video = new Video { Id = 1, Name = "Bailando", Author = "Mauro", Hour = 1, MinSeconds = 2.10, LinkVideo = "www.youtube.com/videomauro", CategoryVideo = new List <CategoryVideo>() }; }
private void LoadContentsById(string channelId) { //string channelId = YoutubeClient.ParseChannelId(channelLink); try { ChannelId channelIdStruct = ChannelId.Parse(channelId); Channel channel = _client.Channels.GetAsync(channelIdStruct).Result; //string playlistId = channel.GetChannelVideosPlaylistId(); var videos = _client.Channels.GetUploadsAsync(channel.Id); List <Video> playlistVideos = new List <Video>(); IAsyncEnumerator <PlaylistVideo> enumerator = videos.GetAsyncEnumerator(); while (true) { PlaylistVideo playlistVideo = enumerator.Current; playlistVideos.Add(_client.Videos.GetAsync(playlistVideo.Id).Result); ValueTask <bool> next = enumerator.MoveNextAsync(); if (!next.Result) { break; } } _videos = playlistVideos; } catch (Exception e) { if (_logger != null) { _logger.Log(e.InnerException?.Message); } else { throw; } } }
void ProcessVideo(PlaylistVideo video) { Log.Debug("Adding external video " + video.File.FilePath); videoEditor.AddSegment(video.File.FilePath, 0, video.File.Duration.MSeconds, 1, "", video.File.HasAudio, new Area()); }
protected void Page_Load(object sender, EventArgs e) { MembershipUser mu = MembershipWrapper.GetUser(); if (mu == null || string.IsNullOrEmpty(Request.QueryString["vidid"]) ) Response.Redirect("~/account/logon"); string vidid = Request.QueryString["vidid"]; string vtype = Request.QueryString["vtype"]; char vtypeAction = Convert.ToChar(vtype); var vid = new Video(vidid.Substring(0, 2), vidid.Substring(3, vidid.Length - 3)); switch (vtypeAction) { case 'P': // adding to playlist var plylst = new Playlist(); plylst.GetUserPlaylist(Convert.ToInt32(mu.ProviderUserKey)); var plyvid = new PlaylistVideo(); if (plylst.PlaylistID == 0) { plylst.CreatedByUserID = Convert.ToInt32(mu.ProviderUserKey); plylst.UserAccountID = Convert.ToInt32(mu.ProviderUserKey); plylst.Create(); plyvid.RankOrder = 1; } else { var plyvids = new PlaylistVideos(); plyvids.GetPlaylistVideosForPlaylist(plylst.PlaylistID); if (mu.UserName.ToLower() != GeneralConfigs.AdminUserName.ToLower() && plyvids.Count >= 25) { // cannot have not than 10 Response.Redirect("~/account/playlist/" + mu.UserName); } plyvid.RankOrder = plyvids.Count + 1; } plyvid.PlaylistID = plylst.PlaylistID; plyvid.VideoID = vid.VideoID; if (!PlaylistVideo.IsPlaylistVideo(plyvid.PlaylistID, vid.VideoID)) { plyvid.CreatedByUserID = Convert.ToInt32(mu.ProviderUserKey); plyvid.Create(); } Response.Redirect("~/account/playlist/" + mu.UserName); break; default: var uav = new UserAccountVideo(); uav.UserAccountID = Convert.ToInt32(mu.ProviderUserKey); uav.VideoID = vid.VideoID; uav.VideoType = vtypeAction; uav.Create(); Response.Redirect("~/" + mu.UserName); break; } }
public ActionResult Playlist(NameValueCollection nvc) { if (nvc == null) throw new ArgumentNullException("nvc"); if (_mu != null) _ua = new UserAccount(Convert.ToInt32(_mu.ProviderUserKey)); ViewBag.UserName = _ua.UserName; var plyst = new Playlist(); plyst.GetUserPlaylist(_ua.UserAccountID); ViewBag.UserPlaylistID = plyst.PlaylistID; var plyvids = new PlaylistVideos(); plyvids.GetPlaylistVideosForPlaylist(plyst.PlaylistID); nvc = Request.Form; PlaylistVideo plv = null; if (nvc["video_delete_id"] != null) { foreach (PlaylistVideo plv1 in plyvids) { if (plv != null && plv1.RankOrder > plv.RankOrder) { plv1.RankOrder--; plv1.UpdatedByUserID = _ua.UserAccountID; plv1.Update(); } if (plv1.PlaylistID != plyst.PlaylistID || Convert.ToInt32(nvc["video_delete_id"]) != plv1.VideoID) continue; plv = new PlaylistVideo(plv1.PlaylistVideoID); if (PlaylistVideo.Delete(plyst.PlaylistID, Convert.ToInt32(nvc["video_delete_id"]))) { // deleted } } } else if (nvc["video_down_id"] != null) { plv = new PlaylistVideo(); plv.Get(plyst.PlaylistID, Convert.ToInt32(nvc["video_down_id"])); foreach (PlaylistVideo plv1 in plyvids.Where(plv1 => plv1.RankOrder == (plv.RankOrder + 1))) { plv1.RankOrder--; plv1.UpdatedByUserID = _ua.UserAccountID; plv1.Update(); } plv.RankOrder++; plv.UpdatedByUserID = _ua.UserAccountID; plv.Update(); } else if (nvc["video_up_id"] != null) { plv = new PlaylistVideo(); plv.Get(plyst.PlaylistID, Convert.ToInt32(nvc["video_up_id"])); foreach (PlaylistVideo plv1 in plyvids.Where(plv1 => plv1.RankOrder == (plv.RankOrder - 1))) { plv1.RankOrder++; plv1.UpdatedByUserID = _ua.UserAccountID; plv1.Update(); } plv.RankOrder--; plv.UpdatedByUserID = _ua.UserAccountID; plv.Update(); } else { if (!string.IsNullOrEmpty(nvc["selected_autoplay"]) && nvc["selected_autoplay"] == "on") { plyst.AutoPlay = true; } else plyst.AutoPlay = false; plyst.Update(); } Response.Redirect("~/account/playlist"); return new EmptyResult(); }
public void TestMultiplayerCamerasConfig() { TimelineEvent evt1; List <CameraConfig> cams1, cams2; Mock <IMultiPlayer> multiplayerMock = new Mock <IMultiPlayer> (); mtkMock.Setup(m => m.GetMultiPlayer()).Returns(multiplayerMock.Object); player = new PlayerController(true); PreparePlayer(); /* Only called internally in the openning */ cams1 = new List <CameraConfig> { new CameraConfig(0), new CameraConfig(1) }; cams2 = new List <CameraConfig> { new CameraConfig(1), new CameraConfig(0) }; multiplayerMock.Verify(p => p.ApplyCamerasConfig(), Times.Never()); Assert.AreEqual(cams1, player.CamerasConfig); player.CamerasConfig = cams2; multiplayerMock.Verify(p => p.ApplyCamerasConfig(), Times.Once()); Assert.AreEqual(cams2, player.CamerasConfig); multiplayerMock.ResetCalls(); /* Now load an event */ evt1 = new TimelineEvent { Start = new Time(100), Stop = new Time(200), CamerasConfig = new List <CameraConfig> { new CameraConfig(1), new CameraConfig(1) } }; player.LoadEvent(mfs, evt1, evt1.Start, true); multiplayerMock.Verify(p => p.ApplyCamerasConfig(), Times.Once()); Assert.AreEqual(evt1.CamerasConfig, player.CamerasConfig); multiplayerMock.ResetCalls(); /* Change event cams config */ player.CamerasConfig = new List <CameraConfig> { new CameraConfig(0), new CameraConfig(0) }; multiplayerMock.Verify(p => p.ApplyCamerasConfig(), Times.Once()); Assert.AreEqual(new List <CameraConfig> { new CameraConfig(0), new CameraConfig(0) }, evt1.CamerasConfig); Assert.AreEqual(player.CamerasConfig, evt1.CamerasConfig); multiplayerMock.ResetCalls(); /* Unload and check the original cams config is set back*/ player.UnloadCurrentEvent(); multiplayerMock.Verify(p => p.ApplyCamerasConfig(), Times.Once()); Assert.AreEqual(cams2, player.CamerasConfig); Assert.AreEqual(new List <CameraConfig> { new CameraConfig(0), new CameraConfig(0) }, evt1.CamerasConfig); multiplayerMock.ResetCalls(); /* And changing the config does not affects the unloaded event */ player.CamerasConfig = cams1; multiplayerMock.Verify(p => p.ApplyCamerasConfig(), Times.Once()); Assert.AreEqual(new List <CameraConfig> { new CameraConfig(0), new CameraConfig(0) }, evt1.CamerasConfig); multiplayerMock.ResetCalls(); /* Now load a playlist video */ PlaylistVideo plv = new PlaylistVideo(mfs [0]); player.LoadPlaylistEvent(playlist, plv); multiplayerMock.Verify(p => p.ApplyCamerasConfig(), Times.Never()); Assert.AreEqual(new List <CameraConfig> { new CameraConfig(0) }, player.CamerasConfig); multiplayerMock.ResetCalls(); player.UnloadCurrentEvent(); /* Called by Open internally () */ multiplayerMock.Verify(p => p.ApplyCamerasConfig(), Times.Never()); Assert.AreEqual(cams2, player.CamerasConfig); multiplayerMock.ResetCalls(); /* Now load a playlist event and make sure its config is loaded * and not the event's one */ PlaylistPlayElement ple = new PlaylistPlayElement(evt, mfs); ple.CamerasConfig = cams2; player.LoadPlaylistEvent(playlist, ple); multiplayerMock.Verify(p => p.ApplyCamerasConfig(), Times.Once()); Assert.AreEqual(cams2, player.CamerasConfig); multiplayerMock.ResetCalls(); }
public void TestLoadPlaylistEvent() { int elementLoaded = 0; MediaFileSet nfs; PlaylistPlayElement el1; player.ElementLoadedEvent += (element, hasNext) => { if (element != null) { elementLoaded++; } }; PreparePlayer(); /* Load playlist timeline event element */ nfs = Cloner.Clone(mfs); el1 = playlist.Elements [0] as PlaylistPlayElement; el1.FileSet = nfs; currentTime = el1.Play.Start; player.LoadPlaylistEvent(playlist, el1); Assert.AreEqual(1, elementLoaded); elementLoaded = 0; Assert.AreEqual(el1.CamerasConfig, player.CamerasConfig); Assert.AreEqual(el1.CamerasLayout, player.CamerasLayout); playerMock.Verify(p => p.Open(nfs [0]), Times.Once()); playerMock.Verify(p => p.Seek(el1.Play.Start, true, false), Times.Never()); playerMock.Verify(p => p.Play(), Times.Never()); playerMock.VerifySet(p => p.Rate = 1); playerMock.Raise(p => p.ReadyToSeek += null, this); playerMock.Verify(p => p.Seek(el1.Play.Start, true, false), Times.Once()); playerMock.Verify(p => p.Play(), Times.Once()); /* Load still image */ player.LoadPlaylistEvent(playlist, plImage); playerMock.ResetCalls(); player.Pause(); playerMock.Verify(p => p.Pause(), Times.Never()); Assert.IsFalse(player.Playing); player.Play(); playerMock.Verify(p => p.Play(), Times.Never()); Assert.IsTrue(player.Playing); /* Load drawings */ PlaylistDrawing dr = new PlaylistDrawing(new FrameDrawing()); player.LoadPlaylistEvent(playlist, dr); playerMock.ResetCalls(); player.Pause(); playerMock.Verify(p => p.Pause(), Times.Never()); Assert.IsFalse(player.Playing); player.Play(); playerMock.Verify(p => p.Play(), Times.Never()); Assert.IsTrue(player.Playing); /* Load video */ PlaylistVideo vid = new PlaylistVideo(mfs [0]); player.LoadPlaylistEvent(playlist, vid); Assert.AreNotEqual(mfs, player.FileSet); Assert.IsTrue(player.Playing); Assert.AreEqual(new List <CameraConfig> { new CameraConfig(0) }, player.CamerasConfig); }
/// <summary> /// Gets playlist by ID, truncating resulting video list at given number of pages (1 page ≤ 200 videos) /// </summary> public async Task <Playlist> GetPlaylistAsync(string playlistId, int maxPages) { playlistId.GuardNotNull(nameof(playlistId)); maxPages.GuardPositive(nameof(maxPages)); if (!ValidatePlaylistId(playlistId)) { throw new ArgumentException("Invalid Youtube playlist ID", nameof(playlistId)); } // Get all videos across pages var pagesDone = 0; var offset = 0; XElement playlistXml; var videoIds = new HashSet <string>(); var videos = new List <PlaylistVideo>(); do { // Get manifest var request = $"{YoutubeHost}/list_ajax?style=xml&action_get_list=1&list={playlistId}&index={offset}"; var response = await _httpService.GetStringAsync(request).ConfigureAwait(false); playlistXml = XElement.Parse(response).StripNamespaces(); // Parse videos var total = 0; var delta = 0; foreach (var videoXml in playlistXml.Elements("video")) { // Basic info var videoId = videoXml.ElementStrict("encrypted_id").Value; var videoTitle = videoXml.ElementStrict("title").Value; var videoThumbnails = new VideoThumbnails(videoId); var videoDuration = TimeSpan.FromSeconds((double)videoXml.ElementStrict("length_seconds")); var videoDescription = videoXml.ElementStrict("description").Value; // Keywords var videoKeywordsJoined = videoXml.ElementStrict("keywords").Value; var videoKeywords = Regex .Matches(videoKeywordsJoined, @"(?<=(^|\s)(?<q>""?))([^""]|(""""))*?(?=\<q>(?=\s|$))") .Cast <Match>() .Select(m => m.Value) .Where(s => s.IsNotBlank()) .ToArray(); // Statistics // The inner text is already formatted so we have to parse it manually var videoViewCount = Regex.Replace(videoXml.ElementStrict("views").Value, @"\D", "").ParseLong(); var videoLikeCount = Regex.Replace(videoXml.ElementStrict("likes").Value, @"\D", "").ParseLong(); var videoDislikeCount = Regex.Replace(videoXml.ElementStrict("dislikes").Value, @"\D", "").ParseLong(); var videoStatistics = new Statistics(videoViewCount, videoLikeCount, videoDislikeCount); // Video var video = new PlaylistVideo(videoId, videoTitle, videoDescription, videoThumbnails, videoDuration, videoKeywords, videoStatistics); // Add to list if not already there if (videoIds.Add(video.Id)) { videos.Add(video); delta++; } total++; } // Break if the videos started repeating if (delta <= 0) { break; } // Prepare for next page pagesDone++; offset += total; } while (pagesDone < maxPages); // Basic info var title = playlistXml.ElementStrict("title").Value; var author = playlistXml.Element("author")?.Value ?? ""; // system playlists don't have an author var description = playlistXml.ElementStrict("description").Value; // Statistics var viewCount = (long?)playlistXml.Element("views") ?? 0; // watchlater does not have views var likeCount = (long?)playlistXml.Element("likes") ?? 0; // system playlists don't have likes var dislikeCount = (long?)playlistXml.Element("dislikes") ?? 0; // system playlists don't have dislikes var statistics = new Statistics(viewCount, likeCount, dislikeCount); return(new Playlist(playlistId, title, author, description, statistics, videos)); }
void AddVideo(IPlaylistElement element, bool prepend) { MediaFile file = Helpers.Misc.OpenFile (widget); if (file != null) { PlaylistVideo video = new PlaylistVideo (file); int index = playlist.Elements.IndexOf (element); if (!prepend) { index++; } playlist.Elements.Insert (index, video); } }
public async Task AddVideoToPlaylistAsync(PlaylistVideo playlistVideo) { await _db.PlaylistVideos.AddAsync(playlistVideo); }
public void RemoveVideoFromPlaylist(PlaylistVideo playlistVideo) { _db.PlaylistVideos.Remove(playlistVideo); }
public PlaylistMenuItem(PlaylistVideo video) { title = video.Title; author = video.Author; thumbnailUrl = video.Thumbnails.MediumResUrl; }
public void Initialize() { playlist = new Playlist { Id = 2, Name = "Mauro", Description = "Facil para dormir", Image = "", PlaylistTrack = new List <PlaylistTrack>(), PlaylistCategory = new List <PlaylistCategory>(), PlaylistVideo = new List <PlaylistVideo>() }; track = new Track { Id = 1, Image = "", Author = "", Sound = "", Name = "Mauro baila cumbia", CategoryTrack = new List <CategoryTrack>(), }; category = new Category { Id = 1, Name = "Dormir" }; playlistTrack = new PlaylistTrack { IdPlaylist = playlist.Id, Playlist = playlist, IdTrack = track.Id, Track = track, }; playlistCategory = new PlaylistCategory { IdPlaylist = playlist.Id, Playlist = playlist, IdCategory = category.Id, Category = category }; video = new Video { Id = 1, Name = "Bailando", Author = "Mauro", Hour = 1, MinSeconds = 2.10, LinkVideo = "www.youtube.com/videomauro", CategoryVideo = new List <CategoryVideo>(), PlaylistVideo = new List <PlaylistVideo>() }; playlistVideo = new PlaylistVideo { IdPlaylist = playlist.Id, Playlist = playlist, IdVideo = video.Id, Video = video }; playlist.PlaylistVideo.Add(playlistVideo); playlist.PlaylistTrack.Add(playlistTrack); playlist.PlaylistCategory.Add(playlistCategory); }
public ActionResult Playlist(NameValueCollection nvc) { mu = Membership.GetUser(); ua = new UserAccount(Convert.ToInt32(mu.ProviderUserKey)); ViewBag.UserName = ua.UserName; BootBaronLib.AppSpec.DasKlub.BOL.Playlist plyst = new Playlist(); plyst.GetUserPlaylist(ua.UserAccountID); ViewBag.UserPlaylistID = plyst.PlaylistID; PlaylistVideos plyvids = new PlaylistVideos(); plyvids.GetPlaylistVideosForPlaylist(plyst.PlaylistID); nvc = Request.Form; //video_delete_id //video_down_id //video_up_id PlaylistVideo plv = null; if (nvc["video_delete_id"] != null) { foreach (PlaylistVideo plv1 in plyvids) { if (plv != null && plv1.RankOrder > plv.RankOrder) { plv1.RankOrder--; plv1.UpdatedByUserID = ua.UserAccountID; plv1.Update(); } if (plv1.PlaylistID == plyst.PlaylistID && Convert.ToInt32(nvc["video_delete_id"]) == plv1.VideoID) { plv = new PlaylistVideo(plv1.PlaylistVideoID); if (PlaylistVideo.Delete(plyst.PlaylistID, Convert.ToInt32(nvc["video_delete_id"]))) { // deleted } } } } else if (nvc["video_down_id"] != null) { plv = new PlaylistVideo(); plv.Get(plyst.PlaylistID, Convert.ToInt32(nvc["video_down_id"])); foreach (PlaylistVideo plv1 in plyvids) { if (plv1.RankOrder == (plv.RankOrder + 1)) { plv1.RankOrder--; plv1.UpdatedByUserID = ua.UserAccountID; plv1.Update(); } } plv.RankOrder++; plv.UpdatedByUserID = ua.UserAccountID; plv.Update(); } else if (nvc["video_up_id"] != null) { plv = new PlaylistVideo(); plv.Get(plyst.PlaylistID, Convert.ToInt32(nvc["video_up_id"])); foreach (PlaylistVideo plv1 in plyvids) { if (plv1.RankOrder == (plv.RankOrder - 1)) { plv1.RankOrder++; plv1.UpdatedByUserID = ua.UserAccountID; plv1.Update(); } } plv.RankOrder--; plv.UpdatedByUserID = ua.UserAccountID; plv.Update(); } else //if (nvc["selected_autoplay"] != null) { if (!string.IsNullOrEmpty(nvc["selected_autoplay"]) && nvc["selected_autoplay"] == "on") { plyst.AutoPlay = true; } else plyst.AutoPlay = false; plyst.Update(); } Response.Redirect("~/account/playlist"); return new EmptyResult(); }
/// <summary> /// Enumerates batches of videos included in the specified playlist. /// </summary> public async IAsyncEnumerable <Batch <PlaylistVideo> > GetVideoBatchesAsync( PlaylistId playlistId, [EnumeratorCancellation] CancellationToken cancellationToken = default) { var encounteredIds = new HashSet <VideoId>(); var lastVideoId = default(VideoId?); var lastVideoIndex = 0; var visitorData = default(string?); do { var playlistExtractor = await _controller.GetPlaylistNextResponseAsync( playlistId, lastVideoId, lastVideoIndex, visitorData, cancellationToken ); var videos = new List <PlaylistVideo>(); foreach (var videoExtractor in playlistExtractor.GetVideos()) { var videoId = videoExtractor.TryGetVideoId() ?? throw new YoutubeExplodeException("Could not extract video ID."); lastVideoId = videoId; lastVideoIndex = videoExtractor.TryGetIndex() ?? throw new YoutubeExplodeException("Could not extract video index."); // Don't yield the same video twice if (!encounteredIds.Add(videoId)) { continue; } var videoTitle = videoExtractor.TryGetVideoTitle() ?? throw new YoutubeExplodeException("Could not extract video title."); var videoChannelTitle = videoExtractor.TryGetVideoAuthor() ?? throw new YoutubeExplodeException("Could not extract video author."); var videoChannelId = videoExtractor.TryGetVideoChannelId() ?? throw new YoutubeExplodeException("Could not extract video channel ID."); var duration = videoExtractor.TryGetVideoDuration(); var thumbnails = videoExtractor .GetVideoThumbnails() .Select(t => { var thumbnailUrl = t.TryGetUrl() ?? throw new YoutubeExplodeException("Could not extract thumbnail URL."); var thumbnailWidth = t.TryGetWidth() ?? throw new YoutubeExplodeException("Could not extract thumbnail width."); var thumbnailHeight = t.TryGetHeight() ?? throw new YoutubeExplodeException("Could not extract thumbnail height."); var thumbnailResolution = new Resolution(thumbnailWidth, thumbnailHeight); return(new Thumbnail(thumbnailUrl, thumbnailResolution)); }) .Concat(Thumbnail.GetDefaultSet(videoId)) .ToArray(); var video = new PlaylistVideo( playlistId, videoId, videoTitle, new Author(videoChannelId, videoChannelTitle), duration, thumbnails ); videos.Add(video); } // Stop extracting if there are no new videos if (!videos.Any()) { break; } yield return(Batch.Create(videos)); visitorData ??= playlistExtractor.TryGetVisitorData(); } while (true); }