Пример #1
0
        private async void ConversionCompleted(ProgressData progressData)
        {
            DoubleAnimation progressAnimation = new DoubleAnimation(100, TimeSpan.FromSeconds(0));

            progressBarConvertProgress.BeginAnimation(ProgressBar.ValueProperty, progressAnimation);
            textBlockProgress.Text = progressData.IsFastCut ? "Video cut!" : "Video converted!";
            string outputSize = GetBytesReadable(new FileInfo(currentOutputPath).Length);

            textBlockSize.Text            = "Output size: " + outputSize;
            TaskbarItemInfo.ProgressState = TaskbarItemProgressState.None;
            Storyboard storyboard = FindResource("ProgressAnimationOut") as Storyboard;

            storyboard.Begin();
            buttonConvert.IsEnabled     = true;
            buttonPreview.IsEnabled     = true;
            buttonOpenFile.IsEnabled    = true;
            buttonOpenStream.IsEnabled  = true;
            buttonPauseResume.IsEnabled = false;
            buttonCancel.IsEnabled      = false;
            checkBoxCrop.IsEnabled      = true;
            checkBoxCut.IsEnabled       = true;
            gridSourceMedia.IsEnabled   = true;
            buttonOpenOutput.Visibility = Visibility.Visible;
            Title = "AVC to HEVC Converter";

            MediaInfo outputFile = await MediaInfo.Open(currentOutputPath);

            textBlockDuration.Text   += $"   ⟶   {outputFile.Duration.ToString(@"hh\:mm\:ss\.ff")}";
            textBlockCodec.Text      += $"   ⟶   {outputFile.Codec} / {outputFile.AudioCodec}";
            textBlockFramerate.Text  += $"   ⟶   {outputFile.Framerate} fps";
            textBlockBitrate.Text    += $"   ⟶   {outputFile.Bitrate} Kbps";
            textBlockResolution.Text += $"   ⟶   {outputFile.Width + "x" + outputFile.Height}";
            textBlockInputSize.Text  += $"   ⟶   {outputSize}";
            if (!String.IsNullOrEmpty(outputFile.AspectRatio) && outputFile.AspectRatio != "N/A")
            {
                textBlockResolution.Text += $" ({outputFile.AspectRatio})";
            }
        }
Пример #2
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);
            }
        }
Пример #3
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);
                    }
                }
            }
        }
Пример #5
0
        public async void Convert(MediaInfo sourceInfo, string destination, ConversionOptions conversionOptions)
        {
            progressData = new ProgressData();

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

            //Duration
            if (conversionOptions.End != TimeSpan.Zero)
            {
                progressData.TotalTime = conversionOptions.End - conversionOptions.Start;
            }
            else
            {
                progressData.TotalTime = sourceInfo.Duration - conversionOptions.Start;
            }

            //Filters
            string filters = "";

            if (conversionOptions.Resolution.HasValue() || conversionOptions.CropData.HasValue() || conversionOptions.Rotation.HasValue())
            {
                filters = " -vf " + ConcatFilters(conversionOptions.Resolution.FilterString, conversionOptions.CropData.FilterString, conversionOptions.Rotation.FilterString);
            }

            //Get nearest before keyframe
            var keyframes = await sourceInfo.GetNearestBeforeAndAfterKeyFrames(conversionOptions.Start.TotalSeconds).ConfigureAwait(false);

            TimeSpan startTime = TimeSpan.FromSeconds(keyframes.before);

            //FFMpeg command string
            StringBuilder sb = new StringBuilder("-y");

            sb.Append($" -ss {startTime}");
            sb.Append($" -i \"{sourceInfo.Source}\"");
            if (sourceInfo.HasExternalAudio)
            {
                sb.Append($" -ss {startTime}");
                sb.Append($" -i \"{sourceInfo.ExternalAudioSource}\"");
            }
            if (conversionOptions.End != TimeSpan.Zero)
            {
                sb.Append($" -t {conversionOptions.End - conversionOptions.Start}");
            }
            sb.Append($" -map 0:v:0");
            if (!conversionOptions.SkipAudio)
            {
                foreach (var audioTrack in sourceInfo.AudioTracks)
                {
                    if (audioTrack.Enabled)
                    {
                        sb.Append($" -map {(sourceInfo.HasExternalAudio ? "1" : "0")}:{audioTrack.StreamIndex}");
                        sb.Append($" -disposition:{audioTrack.StreamIndex} {(audioTrack.Default ? "default" : "none")}");
                    }
                }
            }
            sb.Append(" -map 0:s?");
            sb.Append(" -movflags faststart -c:v " + conversionOptions.Encoder.GetFFMpegCommand());
            if (conversionOptions.Framerate > 0)
            {
                sb.Append(" -r " + conversionOptions.Framerate);
            }
            sb.Append(filters);
            sb.Append(conversionOptions.SkipAudio ? " -an" : " -c:a copy");
            sb.Append($" -ss {conversionOptions.Start - startTime}");
            sb.Append($" -avoid_negative_ts 1 \"{destination}\" -hide_banner");

            StartConversionProcess(sb.ToString());
        }
Пример #6
0
        public void Convert(MediaInfo sourceInfo, string outputPath, ConversionOptions conversionOptions)
        {
            progressData         = new ProgressData();
            previousProgressData = new ProgressData();
            errorLine            = "";

            // 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;
            }

            // Gets the total number of output frames
            Filters.FpsFilter fpsFilter = conversionOptions.Filters.FirstOrDefault(f => f is Filters.FpsFilter) as Filters.FpsFilter;
            double            outputFps = fpsFilter?.Framerate ?? sourceInfo.Framerate;

            progressData.TotalFrames = System.Convert.ToInt32(progressData.TotalTime.TotalSeconds * outputFps);

            // Get the total output file size (if using constant bitrate)
            if (conversionOptions.EncodingMode == EncodingMode.AverageBitrate_FirstPass || conversionOptions.EncodingMode == EncodingMode.AverageBitrate_SinglePass)
            {
                progressData.TotalByteSize = conversionOptions.Encoder.Bitrate.Bps / 8 * System.Convert.ToInt64(progressData.TotalTime.TotalSeconds);
                foreach (var audioTrack in sourceInfo.AudioTracks)
                {
                    if (conversionOptions.AudioConversionOptions.ContainsKey(audioTrack.StreamIndex))
                    {
                        progressData.TotalByteSize += conversionOptions.AudioConversionOptions[audioTrack.StreamIndex].Encoder.Bitrate.Bps / 8 * System.Convert.ToInt64(progressData.TotalTime.TotalSeconds);
                    }
                    else
                    {
                        progressData.TotalByteSize += audioTrack.Bitrate.Bps / 8 * System.Convert.ToInt64(progressData.TotalTime.TotalSeconds);
                    }
                }
            }

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

            // Starts the conversion task
            Task <bool> conversionTask;

            if (conversionOptions.EncodeSections.Count == 0)
            {
                conversionTask = Convert_SingleSegment(sourceInfo, outputPath, conversionOptions, TimeSpan.Zero, TimeSpan.Zero);
            }
            else if (conversionOptions.EncodeSections.Count == 1)
            {
                conversionTask = Convert_SingleSegment(sourceInfo, outputPath, conversionOptions, conversionOptions.EncodeSections.ActualStart, conversionOptions.EncodeSections.ActualEnd);
            }
            else
            {
                conversionTask = Convert_MultipleSegments(sourceInfo, outputPath, conversionOptions);
            }

            // Reports the conversion result to the original caller
            conversionTask.ContinueWith(result => ReportCompletition(result.Result));
        }