Example #1
0
        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");
            }
        }
Example #2
0
        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);
        }
Example #3
0
        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();
        }
Example #6
0
        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"));
 }