Example #1
0
        /// <summary>
        ///     <para> ---- </para>
        ///     <para>Establishes whether the data indicates the conversion is complete</para>
        /// </summary>
        /// <param name="data">Event data from the FFmpeg console.</param>
        /// <param name="conversionCompleted">
        ///     <para>If successful, outputs a <see cref="ConversionCompleted"/> which is </para>
        ///     <para>generated from the data. </para>
        /// </param>
        internal static bool IsConvertCompleteData(string data, out ConversionCompleted conversionCompleted)
        {
            conversionCompleted = null;

            Match matchFrame    = Index[Find.ConvertProgressFrame].Match(data);
            Match matchFps      = Index[Find.ConvertProgressFps].Match(data);
            Match matchFinished = Index[Find.ConvertProgressFinished].Match(data);
            Match matchTime     = Index[Find.ConvertProgressTime].Match(data);
            Match matchBitrate  = Index[Find.ConvertProgressBitrate].Match(data);

            if (!matchFrame.Success || !matchFps.Success || !matchFinished.Success || !matchTime.Success ||
                !matchBitrate.Success)
            {
                return(false);
            }

            TimeSpan processedDuration;

            TimeSpan.TryParse(matchTime.Groups[1].Value, out processedDuration);

            long   frame   = Convert.ToInt64(matchFrame.Groups[1].Value, CultureInfo.InvariantCulture);
            double fps     = Convert.ToDouble(matchFps.Groups[1].Value, CultureInfo.InvariantCulture);
            int    sizeKb  = Convert.ToInt32(matchFinished.Groups[1].Value, CultureInfo.InvariantCulture);
            double bitrate = Convert.ToDouble(matchBitrate.Groups[1].Value, CultureInfo.InvariantCulture);

            conversionCompleted =
                new ConversionCompleted(processedDuration, TimeSpan.Zero, frame, fps, sizeKb, bitrate);

            return(true);
        }
Example #2
0
        private async void StartConversionProcess(string arguments)
        {
            convertProcess.StartInfo.Arguments = arguments;
            convertProcess.Start();
            convertProcess.BeginErrorReadLine();
            convertProcess.PriorityClass = ProcessPriorityClass.BelowNormal;
            stopped = false;

            await Task.Run(() =>
            {
                convertProcess.WaitForExit();
            }).ConfigureAwait(false);

            convertProcess.CancelErrorRead();

            int exitCode = convertProcess.ExitCode; //0: success; -1: killed; 1: crashed

            synchronizationContext.Post(new SendOrPostCallback((o) =>
            {
                if (exitCode != -1 && exitCode != 1) //Sometimes ffmpegs exits with weird numbers even if there were no errors
                {
                    ConversionCompleted?.Invoke(progressData);
                }
                else if (!stopped)
                {
                    progressData.ErrorMessage = outputLine;
                    ConversionCompleted?.Invoke(progressData);
                }
            }), null);
        }
Example #3
0
 private void ReportCompletition(bool success)
 {
     if (!stopped)
     {
         synchronizationContext.Post(new SendOrPostCallback((o) =>
         {
             if (!success)
             {
                 ConversionAborted?.Invoke(errorLine);
             }
             else
             {
                 ConversionCompleted?.Invoke();
             }
         }), null);
     }
 }
Example #4
0
        public async void FastCut(string source, string destination, string start, string end)
        {
            progressData                       = new ProgressData();
            progressData.IsFastCut             = true;
            progressData.TotalTime             = TimeSpan.Parse(end) - TimeSpan.Parse(start);
            convertProcess.StartInfo.Arguments = $"-y -ss {start} -to {end} -i \"{source}\" -c copy -avoid_negative_ts 1 \"{destination}\"";
            convertProcess.Start();
            convertProcess.BeginErrorReadLine();

            await Task.Run(() =>
            {
                convertProcess.WaitForExit();
                errorWaitHandle.WaitOne();
            });

            convertProcess.CancelErrorRead();

            int exitCode = convertProcess.ExitCode;

            if (exitCode == 0) //conversion not aborted
            {
                ConversionCompleted?.Invoke(progressData);
            }
        }
Example #5
0
        public async void Convert(MediaInfo sourceInfo, string destination, ConversionOptions conversionOptions)
        {
            progressData           = new ProgressData();
            progressData.IsFastCut = false;
            if (conversionOptions.End != TimeSpan.Zero)
            {
                progressData.TotalTime = conversionOptions.End - conversionOptions.Start;
            }
            else
            {
                progressData.TotalTime = sourceInfo.Duration - conversionOptions.Start;
            }

            string filters = "";

            if (conversionOptions.Resolution.HasValue() && conversionOptions.CropData.HasValue())
            {
                filters = $" -vf \"scale={conversionOptions.Resolution.Width}:{conversionOptions.Resolution.Height}," +
                          $" crop=in_w-{conversionOptions.CropData.Left + conversionOptions.CropData.Right}:in_h-{conversionOptions.CropData.Top + conversionOptions.CropData.Bottom}:{conversionOptions.CropData.Left}:{conversionOptions.CropData.Top}\"";
            }
            else if (conversionOptions.Resolution.HasValue())
            {
                filters = $" -vf \"scale={conversionOptions.Resolution.Width}:{conversionOptions.Resolution.Height}\"";
            }
            else if (conversionOptions.CropData.HasValue())
            {
                filters = $" -vf \"crop=in_w-{conversionOptions.CropData.Left + conversionOptions.CropData.Right}:in_h-{conversionOptions.CropData.Top + conversionOptions.CropData.Bottom}:{conversionOptions.CropData.Left}:{conversionOptions.CropData.Top}\"";
            }

            StringBuilder sb = new StringBuilder("-y");

            sb.Append($" -ss {conversionOptions.Start} ");
            sb.Append($" -i \"{sourceInfo.Source}\"");
            if (!String.IsNullOrEmpty(sourceInfo.AudioSource))
            {
                sb.Append($" -i \"{sourceInfo.AudioSource}\"");
            }
            if (conversionOptions.End != TimeSpan.Zero)
            {
                sb.Append($" -t {conversionOptions.End - conversionOptions.Start}");
            }
            sb.Append(" -c:v " + (conversionOptions.Encoder == Encoder.H264 ? "libx264" : "libx265"));
            sb.Append(" -movflags faststart -preset " + PRESETS[conversionOptions.Preset]);
            sb.Append(" -crf " + conversionOptions.Crf);
            if (conversionOptions.Framerate > 0)
            {
                sb.Append(" -r" + conversionOptions.Framerate);
            }
            sb.Append(filters);
            sb.Append(conversionOptions.SkipAudio ? " -an" : " -c:a copy");
            sb.Append($" \"{destination}\" -hide_banner");

            convertProcess.StartInfo.Arguments = sb.ToString();
            convertProcess.Start();
            convertProcess.BeginErrorReadLine();

            await Task.Run(() =>
            {
                convertProcess.WaitForExit();
                errorWaitHandle.WaitOne();
            });

            convertProcess.CancelErrorRead();

            int exitCode = convertProcess.ExitCode;

            if (exitCode == 0) //conversion not aborted
            {
                ConversionCompleted?.Invoke(progressData);
            }
        }
        public async void Convert(MediaInfo sourceInfo, string outputPath, ConversionOptions conversionOptions)
        {
            progressData         = new ProgressData();
            previousProgressData = new ProgressData();

            //Capture the Synchronization Context of the caller, in order to invoke the events in its original thread
            synchronizationContext = SynchronizationContext.Current;

            //Duration
            if (conversionOptions.EncodeSections.Count > 0)
            {
                progressData.TotalTime = conversionOptions.EncodeSections.TotalDuration;
            }
            else
            {
                progressData.TotalTime = sourceInfo.Duration;
            }

            progressData.EncodingMode = conversionOptions.EncodingMode;
            partialProgress           = false;

            //2-pass mode
            if (conversionOptions.EncodingMode == EncodingMode.AverageBitrate_FirstPass)
            {
                await RunConversionProcess(BuildArgumentsString(sourceInfo, outputPath, conversionOptions), false).ConfigureAwait(false);

                if (!stopped)
                {
                    progressData.EncodingMode      = EncodingMode.AverageBitrate_SecondPass;
                    conversionOptions.EncodingMode = EncodingMode.AverageBitrate_SecondPass;
                    await RunConversionProcess(BuildArgumentsString(sourceInfo, outputPath, conversionOptions)).ConfigureAwait(false);
                }
                //Remove 2pass log files
                foreach (var file in Directory.GetFiles(Environment.CurrentDirectory).Where(x => x.Contains("log")))
                {
                    File.Delete(file);
                }
            }
            //Single pass mode
            else
            {
                if (conversionOptions.EncodeSections.Count == 0)
                {
                    await RunConversionProcess(BuildArgumentsString(sourceInfo, outputPath, conversionOptions)).ConfigureAwait(false);
                }
                else if (conversionOptions.EncodeSections.Count == 1)
                {
                    await RunConversionProcess(BuildArgumentsString(sourceInfo, outputPath, conversionOptions, conversionOptions.EncodeSections.ActualStart, conversionOptions.EncodeSections.ActualEnd, conversionOptions.FadeEffect, conversionOptions.FadeEffect)).ConfigureAwait(false);
                }
                else
                {
                    partialProgress = true;
                    string outputDirectory = Path.GetDirectoryName(outputPath);
                    string outputFileName  = Path.GetFileNameWithoutExtension(outputPath);
                    for (int i = 0; i < conversionOptions.EncodeSections.Count; i++)
                    {
                        bool   fadeStart   = conversionOptions.FadeEffect && i != 0;
                        bool   fadeEnd     = conversionOptions.FadeEffect && i < conversionOptions.EncodeSections.Count - 1;
                        string destination = $"{outputDirectory}\\{outputFileName}_part_{i}.mp4";
                        string arguments   = BuildArgumentsString(sourceInfo, destination, conversionOptions, conversionOptions.EncodeSections[i].Start, conversionOptions.EncodeSections[i].End, fadeStart, fadeEnd);
                        await RunConversionProcess(arguments, false).ConfigureAwait(false);

                        if (stopped)
                        {
                            break;
                        }
                        previousProgressData = progressData;
                        File.AppendAllText("concat.txt", $"file '{destination}'\n");
                    }
                    if (!stopped)
                    {
                        await RunConversionProcess($"-y -f concat -safe 0 -i concat.txt -c copy \"{outputPath}\"", false).ConfigureAwait(false);
                    }
                    File.Delete("concat.txt");
                    for (int i = 0; i < conversionOptions.EncodeSections.Count; i++)
                    {
                        File.Delete($"{outputDirectory}\\{outputFileName}_part_{i}.mp4");
                    }
                    if (!stopped)
                    {
                        synchronizationContext.Post(new SendOrPostCallback((o) =>
                        {
                            ConversionCompleted?.Invoke(progressData);
                        }), null);
                    }
                }
            }
        }