public async Task StartScan(List <VideoListItem> selection, CancellationToken cancel) { await selection.ForEachAsync(5, cancel, async item => { Media VideoData = PlayerAccess.GetVideoById(item.MediaId.Value); if (VideoData != null && !item.IsBusy) { try { // Query the server for media info. SetStatus(item, VideoListItemStatusEnum.DownloadingInfo); VideoInfo VInfo = await DownloadManager.GetDownloadInfoAsync(VideoData.DownloadUrl); if (VInfo != null) { // Get the highest resolution format. BestFormatInfo VideoFormat = DownloadBusiness.SelectBestFormat(VInfo.Streams); if (VideoFormat == null || VideoFormat.BestVideo == null) { SetStatus(item, VideoListItemStatusEnum.Failed); } else { SetStatus(item, await IsHigherQualityAvailable(VideoFormat, Settings.NaturalGroundingFolder + VideoData.FileName)); } if (VideoFormat != null && !string.IsNullOrEmpty(VideoFormat.StatusText)) { SetStatus(item, item.Status, item.StatusText + string.Format(" ({0})", VideoFormat.StatusText)); } } else { SetStatus(item, VideoListItemStatusEnum.InvalidUrl); } } catch { SetStatus(item, VideoListItemStatusEnum.Failed); } } }); }
public VideoListItemStatusEnum IsHigherQualityAvailableInternal(BestFormatInfo serverFile, string localFile, FFmpegProcess InfoReader) { string LocalFileExt = Path.GetExtension(localFile).ToLower(); // If local file is FLV and there's another format available, it should be downloaded. if (LocalFileExt == ".flv" && serverFile.BestVideo.Container != Container.Flv) { return(VideoListItemStatusEnum.HigherQualityAvailable); } // Original VCD files and files of unrecognized extensions should not be replaced. if (!DownloadManager.DownloadedExtensions.Contains(LocalFileExt) || InfoReader?.VideoStream?.Format == "mpeg1video") { serverFile.StatusText = "Not from YouTube"; return(VideoListItemStatusEnum.OK); } // For server file size, estimate 4% extra for audio. Estimate 30% advantage for VP9 format. non-DASH WebM is VP8 and doesn't have that bonus. long ServerFileSize = (long)(serverFile.BestVideo.Size * 1.04); if (DownloadManager.GetVideoEncoding(serverFile.BestVideo) == VideoEncoding.Vp9) { ServerFileSize = (long)(ServerFileSize * 1.3); } long LocalFileSize = new FileInfo(localFile).Length; if (InfoReader?.VideoStream?.Format == "vp9") { LocalFileSize = (long)(LocalFileSize * 1.3); } // If server resolution is better, download unless local file is bigger. int LocalFileHeight = InfoReader?.VideoStream?.Height ?? 0; if (DownloadManager.GetVideoHeight(serverFile.BestVideo) > LocalFileHeight) { if (ServerFileSize > LocalFileSize) { return(VideoListItemStatusEnum.HigherQualityAvailable); } else if (ServerFileSize != 0) { return(VideoListItemStatusEnum.OK); } } else if (DownloadManager.GetVideoHeight(serverFile.BestVideo) < LocalFileHeight) { // If local resolution is higher, keep. return(VideoListItemStatusEnum.OK); } // Choose whether to download only audio, only video, or both. bool DownloadVideo = false; bool DownloadAudio = false; // Is estimated server file size is at least 15% larger than local file (for same resolution), download. if (ServerFileSize > LocalFileSize * 1.15) { DownloadVideo = true; } // If PreferredFormat is set to a format, download that format. else if (Manager != null) { if (Manager.Options.PreferredFormat == SelectStreamFormat.MP4 && InfoReader.VideoStream?.Format == "vp9" && (DownloadManager.GetVideoEncoding(serverFile.BestVideo) == VideoEncoding.H264 || DownloadManager.GetVideoEncoding(serverFile.BestVideo) == VideoEncoding.H263)) { DownloadVideo = true; } else if (Manager.Options.PreferredFormat == SelectStreamFormat.VP9 && InfoReader.VideoStream?.Format == "h264" && (DownloadManager.GetVideoEncoding(serverFile.BestVideo) == VideoEncoding.Vp9 || DownloadManager.GetVideoEncoding(serverFile.BestVideo) == VideoEncoding.Vp8)) { DownloadVideo = true; } } if (InfoReader.AudioStream == null) { DownloadAudio = true; } // Can only upgrade is video length is same. else if (Math.Abs((InfoReader.FileDuration - serverFile.Duration).TotalSeconds) < 1) { // download audio and merge with local video. string LocalAudio = InfoReader.AudioStream.Format; AudioEncoding RemoteAudio = serverFile.BestAudio?.AudioEncoding ?? AudioEncoding.Aac; if (InfoReader.AudioStream.Bitrate == 0 && LocalAudio == "opus" || LocalAudio == "vorbis") { InfoReader.AudioStream.Bitrate = 160; // FFmpeg doesn't return bitrate of Opus and Vorbis audios, but it's 160. } if (InfoReader.AudioStream.Bitrate == 0) { InfoReader.AudioStream.Bitrate = GetAudioBitrateMuxe(localFile); } int LocalAudioBitRate = InfoReader.AudioStream.Bitrate; long ServerAudioBitRate = serverFile.BestAudio != null ? serverFile.BestAudio.Bitrate / 1024 : 0; // MediaInfo returns no bitrate for MKV containers with AAC audio. InfoReader.AudioStream.Bitrate = 160; if (LocalAudioBitRate > 0 || LocalFileExt != ".mkv") { if ((LocalAudioBitRate == 0 || LocalAudioBitRate < ServerAudioBitRate * .8)) { DownloadAudio = true; } } if ((LocalAudio == "opus" && RemoteAudio == AudioEncoding.Vorbis) || (LocalAudio == "vorbis" && RemoteAudio == AudioEncoding.Opus)) { DownloadAudio = true; } } else { DownloadAudio = DownloadVideo; } if (DownloadVideo && DownloadAudio) { return(VideoListItemStatusEnum.HigherQualityAvailable); } else if (DownloadVideo) { return(VideoListItemStatusEnum.BetterVideoAvailable); } else if (DownloadAudio) { return(VideoListItemStatusEnum.BetterAudioAvailable); } return(VideoListItemStatusEnum.OK); }
public static BestFormatInfo SelectBestFormat(MediaStreamInfoSet vinfo) { return(DownloadManager.SelectBestFormat(vinfo, Settings.SavedFile.Download)); }