Пример #1
0
        /// <summary>
        /// Since an async method does not support ref parameter passing we cannot utilize
        /// `ref FileInfoType` here. Hence we copy it back in the end.
        /// </summary>
        /// <param name="ShouldSimulate"></param>
        /// <returns></returns>
        internal async Task <FileInfoType> Run(bool ShouldSimulate = true)
        {
            var filePath = mFileInfo.Path;

            // var mediaInfo = FileInfo.Parent + @"\ffmpeg_media_info.log";
            Console.WriteLine("Processing Media " + filePath + ":");

            string ffprobeStr = await GetMediaInfo(filePath);

            // TODO: make this debug statements more compact
            // Console.WriteLine("json string:" + ffprobeStr);
            var codecId = ParseMediaInfo(ffprobeStr);

            var codes = codecId.Split(' ');

            if (codes.Length == 0)
            {
                throw new ArgumentException("codecs are not set!");
            }

            var sCodecId = codes[0];
            var aCodecId = codes[1];

            Console.WriteLine("a code: " + aCodecId + ", s code: " + (string.IsNullOrEmpty(sCodecId)?
                                                                      "Empty": sCodecId));

            if (ShouldSimulate)
            {
                return(mFileInfo);
            }

            if (!string.IsNullOrEmpty(sCodecId))
            {
                await ExtractSubtitle(filePath, sCodecId);
            }

            if (ShouldChangeContainer && !mFileInfo.IsInError)
            {
                // ToDo: check for space ahead? to avoid reanme in case of not free space
                // ConvertMedia has a high elapsed time, take advantage of async: do tasks before await
                // inside
                bool isSuccess = await ConvertMedia(filePath, aCodecId);

                if (isSuccess)
                {
                    mFileInfo.Update("convert");

                    // remove the input mkv file
                    FileOperationAPIWrapper.Send(filePath);

                    // update file path
                    mFileInfo.Path = mFileInfo.Parent + "\\" +
                                     System.IO.Path.GetFileNameWithoutExtension(filePath) + ".mp4";

                    if (!ShouldSimulate && !mFileInfo.IsInError)
                    {
                        // show how output media looks like
                        Console.WriteLine();
                        ffprobeStr = await GetMediaInfo(mFileInfo.Path);

                        sCodecId = ParseMediaInfo(ffprobeStr);
                        // sCodecId can be null if there's no sub
                        // System.Diagnostics.Debug.Assert(string.IsNullOrEmpty(sCodecId));
                    }
                }
            }
            return(mFileInfo);
        }
Пример #2
0
        /// <summary>
        /// Extract Rar Archives and clean up
        ///
        /// https://docs.microsoft.com/en-us/dotnet/api/system.io.directory.getfiles
        ///
        /// References
        /// base URL https://github.com/adamhathcock/sharpcompress/blob/master
        /// USAGE.md
        /// src/SharpCompress/Common/ExtractionOptions.cs
        /// Deletion of compressed file after extracting it with nunrar
        ///  https://stackoverflow.com/q/17467951
        /// </summary>
        /// <param name="filePath">the file path variable</param>
        /// <returns></returns>
        public bool ExtractRar(string filePath)
        {
            if (!IsSupportedArchive(filePath))
            {
                return(false);
            }

            mFileInfo.Update("extract");

            using (var archive = SharpCompress.Archives.Rar.RarArchive.Open(filePath)) {
                // archive not null when next archive is not found
                try {
                    // ToDO: show warning for multiple files
                    foreach (var entry in archive.Entries)
                    {
                        // simulation does not continue because file is not extracted
                        // extracting file during simulation: is it a good idea?
                        mFileInfo.Path = mFileInfo.Parent + "\\" + entry.Key;

                        HasEnoughFreeSpace(entry.Size, 2);

                        if (!ShouldSimulate && !mFileInfo.IsInError)
                        {
                            entry.WriteToDirectory(mFileInfo.Parent, new SharpCompress.Common.ExtractionOptions()
                            {
                                ExtractFullPath = true,
                                Overwrite       = true
                            }
                                                   );
                        }

                        break; // only get first item, for psa that's what we expect that much
                    }
                }
                catch (System.ArgumentException e) {
                    Console.WriteLine("Probably could not find next archive! Msg:\r\n" + e.Message);
                    mFileInfo.Update("Fail: SharpCompress Rar Open error");
                    return(false);
                }
            }

            // remove processed Rar Archive/s
            var tail = "part1.rar";

            if (filePath.EndsWith(tail, StringComparison.CurrentCultureIgnoreCase))
            {
                // Only get files that begin with the letter "c".
                string sPath   = GetSimplifiedPath(filePath);
                var    pattern = sPath.Substring(0, sPath.Length - tail.Length) + "part*.rar";
                // Console.WriteLine("Rar find pattern: " + pattern);   debug

                string[] rarFiles = Directory.GetFiles(mFileInfo.Parent, pattern);

                if (!mFileInfo.IsInError)
                {
                    foreach (string rarFile in rarFiles)
                    {
                        if (!ShouldSimulate)
                        {
                            FileOperationAPIWrapper.Send(rarFile);
                        }
                    }
                }
            }
            else if (!ShouldSimulate && !mFileInfo.IsInError)
            {
                Console.WriteLine("Removing file: " + filePath);
                FileOperationAPIWrapper.Send(filePath);
            }

            return(true);
        }
Пример #3
0
        private async Task ExtractSubtitle(string filePath, string sCodecId)
        {
            // mkv, mp4, mpeg-2 m2ts, mov, qt can contain subtitles as attachments
            // ref, https://en.wikipedia.org/wiki/Comparison_of_video_container_formats
            // for now, for psa and rmz we only accept mkv
            if (System.IO.Path.GetExtension(filePath).ToLower() != ".mkv")
            {
                return;
            }

            // https://docs.microsoft.com/en-us/dotnet/api/system.io.path.getfilenamewithoutextension
            var subRipExt   = ".srt";
            var srtFilePath = mFileInfo.Parent + "\\" + System.IO.Path.GetFileNameWithoutExtension(filePath)
                              + subRipExt;

            if (System.IO.File.Exists(srtFilePath))
            {
                Console.WriteLine("Subrip file already exists, renaming");
                var oldSrtFilePath = srtFilePath.Substring(0, srtFilePath.Length - subRipExt.Length) + "_old.srt";

                if (System.IO.File.Exists(oldSrtFilePath))
                {
                    FileOperationAPIWrapper.Send(oldSrtFilePath);
                }

                System.IO.File.Move(srtFilePath, oldSrtFilePath);
            }

            TaskCompletionSource <bool> ffmpegEventHandled = new TaskCompletionSource <bool>();

            using (System.Diagnostics.Process ffmpegProcess = new System.Diagnostics.Process {
                StartInfo =
                {
                    FileName        = FFMpegPath + @"\bin\ffmpeg.exe",
                    // -y overwrite output file if exists
                    Arguments       = " -loglevel warning -i \"" + filePath + "\"" + " -codec:s srt -map " +
                                      sCodecId + " \"" + srtFilePath + "\"",
                    UseShellExecute = false
                },
                EnableRaisingEvents = true
            }
                   ) {
                try {
                    // Start a process and raise an event when done.
                    ffmpegProcess.Exited += (sender, args) => {
                        if (ffmpegProcess.ExitCode != 0)
                        {
                            Console.WriteLine("Exit code: " + ffmpegProcess.ExitCode + ", an overwrite is not " +
                                              "confirmed or ffmpeg is invoked incorrectly! Please check input stream. codec id: " + sCodecId);
                        }

                        Console.Write("Subtitle extraction time: " + Math.Round((ffmpegProcess.ExitTime - ffmpegProcess.
                                                                                 StartTime).TotalMilliseconds) + " ms (), ");

                        ffmpegEventHandled.TrySetResult(true);
                        ffmpegProcess.Dispose();
                    };

                    ffmpegProcess.Start();
                    // better to utilize onExit than `WaitForExit`
                }
                catch (Exception ex) {
                    Console.WriteLine($"An error occurred trying to run ffmpeg scodec copy \"{FFMpegPath}\"");
                    Console.WriteLine(ex.Message);
                    return;
                }

                // Run Concurrent
                // Cleanup garbage sub
                // Change sponsor text in psarip subs

                // Wait for ffmpeg process Exited event, but not more than 120 seconds
                await Task.WhenAny(ffmpegEventHandled.Task, Task.Delay(120000));
            }

            // after extracting if it results a garbage subtitle (with sCount > 1) set shouldChangeContainer to false
            long srtSize = (new System.IO.FileInfo(srtFilePath)).Length;

            Console.WriteLine("Srt size: {0:F2} KB", srtSize * 1.0 / 1024);

            // Expecting at least 5 KB; if found less notify, but don't affect cont. change
            if (srtSize < (5 * 1024))
            {
                Console.WriteLine("Subtitle file size is small (< 5 KB)!");
                // ShouldChangeContainer = false;
            }
        }