private void _muxMediaFiles(string outputPath, string videoFileName, string audioFileName) { var ffmpegPath = _getFFmpegPath(); YTrackLogger.Log(ffmpegPath); FFMpegMultiplexer fFMpegMuxer = new FFMpegMultiplexer(ffmpegPath, videoFileName, audioFileName, Properties.Settings.Default.FallBackToEncodeMedia); fFMpegMuxer.OnMultiplixingComplete += (s, meea) => { try { string finalVideoPath = outputPath + meea.OutputFileExtention; // copy muxed video to the final output path File.Copy(meea.OutputFilePath, finalVideoPath, true); // set the stored flag this.VideoStored = true; // firing youtubeStored OnYoutubeStored?.Invoke(this, finalVideoPath); } catch { YTrackLogger.Log("Cannot Move Output file from temp to Output Path : " + outputPath); throw; } }; if (fFMpegMuxer.Muliplix() == null) { YTrackLogger.Log("Unable to Start FFMpeg\n" + "Input Video : " + videoFileName + "\nInput Audio : " + audioFileName); throw new Exception("Unable to Start FFMpeg"); } }
private async Task <YoutubeMediaPacket> _fillGab(YoutubeRequestURL packetRequestURL, Range lostRange, YoutubeMediaPacketType type) { packetRequestURL.RequestPath.QueryString.SetValue("range", $"{lostRange.Start}-{lostRange.End}"); var requestableURL = packetRequestURL.ToRequestableURL(); // debugging YTrackLogger.Log("\nfilling broken range for type " + type + " : " + lostRange.ToString() + " from : " + requestableURL); long httpSegmentSize = packetRequestURL.RequestPath.QueryString.HasValue("ratebypass") && packetRequestURL.RequestPath.QueryString.GetValue("ratebypass") == "yes" ? (long)lostRange.Length : 9_898_989; YoutubeMediaPacket packet; using (SegmentedHttpStream segmentedHttpStream = new SegmentedHttpStream(_client, requestableURL, (long)lostRange.Length, httpSegmentSize)) { try { string tmpFileName = Path.GetTempFileName(); using (Stream outputStream = new FileStream(tmpFileName, FileMode.Append)) { IProgress <double> progressPercentage = new Progress <double>(b => packetDownloadProgressChanged(b)); await segmentedHttpStream.CopyToStreamAsync(outputStream, progressPercentage); } // no need to check whether the packetRequestURL is a valid requist URL // because we requested it anyway packet = new YoutubeMediaPacket(type, packetRequestURL, tmpFileName); OnPacketDownloadCompleted?.Invoke(this, packet); } catch (Exception e) { // two exception may be thrown // WebException if something went wrong when fetch the new packets // IOException if something went wrong when writing the packet file to disk // I'll raise PacketDownloadExceptionThrown and re-throw exception if (e is WebException) { _onGabPacketDownloadExceptionThrown?.Invoke(this, new PacketDownloadExceptionEventArgumanets() { Exception = e as WebException, FailedPacketRequestURL = packetRequestURL, Range = lostRange }); } // re-throw the error to the caller Helpers.YTrackLogger.Log("Failed to download Packet : " + e.Message + "\n\n" + e.StackTrace); throw; } } return(packet); }
private async Task _fetchYoutubeInfo(string youtubeVideoId) { var client = new YoutubeExplode.YoutubeClient(); YoutubeExplode.Models.Video video = null; try { video = await client.GetVideoAsync(youtubeVideoId); this.Video.VideoInfo = YoutubeVideoInfo.FromVideoObject(video); } catch (Exception e) { _mediaInfoBeingFetched = false; YTrackLogger.Log("Cannot Fetch Video info for " + youtubeVideoId + " : \n\n" + e.Message); } }
private async Task _showDownloadAskingDialog(YoutubeVideoManager manager) { // making sure the video info is populated if (manager.Video.VideoInfo is null) { YTrackLogger.Log($"Starting to download the rest of {manager.Video.VideoFingerPrint} before the info was populated ... ignoring download"); return; } var thumbnail = await Common.FetchThumbnail(manager.Video.VideoInfo.ThumbnailUrl); var thumbBytes = Helpers.Misc.ToImage(thumbnail.thumbnailBytes); // check if video is currently saved in database // if so .. I won't display store notification dialog if (_videosIds.Contains(manager.Video.VideoInfo.Id)) { return; } // check if the current video download dialog is already shown before if (_alreadyDownloadDialogedVideos.Contains(manager.Video.VideoInfo.Id)) { return; } var dialog = new NotificationYNDialog(manager.Video.VideoInfo.Title, thumbBytes); NotificationContainerWindow notificationWindow = new NotificationContainerWindow(dialog); notificationWindow.Show(); dialog.OnDialogResultAvailable += (sender, dialogResult) => { // add to already dialog list ... to make sure the dialog doesn't show for the same video twice _alreadyDownloadDialogedVideos.Add(manager.Video.VideoInfo.Id); if (dialogResult == NotificationDialogResult.Yes || ((dialogResult == NotificationDialogResult.NotChoosen) && Settings.Default.KeepIncompleteCaptureByDefault)) { _startDownloadingVideo(manager); } }; }
private void _startDownloadingVideo(YoutubeVideoManager manager) { if (!Directory.Exists(Settings.Default.OutputDirectory)) { Settings.Default.OutputDirectory = Environment.GetFolderPath(Environment.SpecialFolder.CommonVideos); Settings.Default.Save(); } string outputPath = Path.Combine(Settings.Default.OutputDirectory, Helpers.Misc.RemoveIllegalPathChars(manager.Video.VideoInfo.Title)); new Thread(async() => { try { await manager.DownloadAndMultiplix(outputPath); } catch (Exception e) { YTrackLogger.Log("Exception Occured while Downloading and muxing : " + e.Message + "\n\n" + e.StackTrace); NotificationProvider.Instance.ShowMessageNotification("Capture Failed", "Error While Downloading The Rest Of The Video", NotificationMessageType.Error, this.Dispatcher); } }).Start(); }
private async Task _fillBrokenRanges(List <Range> lostPacketsRanges, YoutubeMediaPacketType lostPacketsType) { // debugging purposes if (lostPacketsRanges.Count > 0) { YTrackLogger.Log("\nBroken Ranges for type " + lostPacketsType + " : \n"); lostPacketsRanges.ForEach(x => { YTrackLogger.Log(x.ToString()); }); YTrackLogger.Log("\n\n"); } // constructing the lost packates new requests and fetch them // firstly i will get clone from first packet url // no need for higher quality checks because lower ones are already removed var lostPacketRequestURL = this.Video.Packets.FirstOrDefault(x => x.VideoPacketType == lostPacketsType)?.YoutubeRequestURL?.DeepClone(); // Youtube Contains M4A containers .... the video may contain only media with Audio content type // if no video packets are present return if (lostPacketRequestURL == null) { return; } // now loop throught all lost packets and fill them foreach (var lostRange in lostPacketsRanges) { var newPacket = await _fillGab(lostPacketRequestURL, lostRange, lostPacketsType); _insertGabPacket(newPacket); } }
private void _raiseMultiplixingFailed(string errorStd) { YTrackLogger.Log("Re-Encoding Fallback also failed" + errorStd); OnMultiplixingFailed?.Invoke(this, new MultiplexingException("Some thing Went Wrong While Multiplexing")); }