示例#1
0
        /// <summary>
        /// Converts a source video to TS format.
        /// </summary>
        /// <param name="source">Source video file.</param>
        /// <param name="IntendedOutput">Output video file.</param>
        /// <returns>Success state.</returns>
        public bool ToTS(VideoInfo source, string IntendedOutput, out string ActualOutput)
        {
            int i = 0;

            ActualOutput = IntendedOutput;
            while (File.Exists(ActualOutput) && FFMpegHelper.IsFileLocked(ActualOutput))
            {
                ActualOutput = Path.Combine(Path.GetDirectoryName(IntendedOutput), Path.GetFileNameWithoutExtension(IntendedOutput) + $"({i}){Path.GetExtension(IntendedOutput)}");
                i++;
            }
            _probe.SetVideoInfo(ref source);
            _totalVideoTime = source.Duration;
            IsConverting    = true;
            if (File.Exists(IntendedOutput) && !FFMpegHelper.IsFileLocked(IntendedOutput))
            {
                return(true);
            }

            FFMpegHelper.ConversionExceptionCheck(source, IntendedOutput);
            FFMpegHelper.ExtensionExceptionCheck(IntendedOutput, ".ts");

            string conversionArgs = string.Format("-i \"{0}\" -c copy -bsf:v h264_mp4toannexb -f mpegts \"{1}\"", source.Path, IntendedOutput);

            return(_RunProcess(conversionArgs));
        }
示例#2
0
        /// <summary>
        /// Builds parameters string from <see cref="ArgumentsContainer"/> that would be passed to ffmpeg process
        /// </summary>
        /// <param name="container">Container of arguments</param>
        /// <param name="input">Input file</param>
        /// <param name="output">Output file</param>
        /// <returns>Parameters string</returns>
        public string BuildArguments(ArgumentsContainer container, FileInfo input, FileInfo output)
        {
            CheckContainerException(container);
            CheckExtensionOfOutputExtension(container, output);
            FFMpegHelper.ConversionExceptionCheck(input, output);


            StringBuilder sb = new StringBuilder();

            var inputA  = new InputArgument(input);
            var outputA = new OutputArgument();

            sb.Append(inputA.GetStringValue().Trim() + " ");

            foreach (var a in container)
            {
                if (!IsInputOrOutput(a.Key))
                {
                    sb.Append(a.Value.GetStringValue().Trim() + " ");
                }
            }

            sb.Append(outputA.GetStringValue().Trim());

            var overrideArg = container.Find <OverrideArgument>();

            if (overrideArg != null)
            {
                sb.Append(" " + overrideArg.GetStringValue().Trim());
            }

            return(sb.ToString());
        }
示例#3
0
        /// <summary>
        /// Convert a video do a different format.
        /// </summary>
        /// <param name="source">Input video source.</param>
        /// <param name="output">Output information.</param>
        /// <param name="type">Target conversion video type.</param>
        /// <param name="speed">Conversion target speed/quality (faster speed = lower quality).</param>
        /// <param name="size">Video size.</param>
        /// <param name="audioQuality">Conversion target audio quality.</param>
        /// <param name="multithreaded">Is encoding multithreaded.</param>
        /// <returns>Output video information.</returns>
        public VideoInfo Convert(
            VideoInfo source,
            FileInfo output,
            VideoType type = VideoType.Mp4,
            Speed speed    =
            Speed.SuperFast,
            VideoSize size =
            VideoSize.Original,
            AudioQuality audioQuality = AudioQuality.Normal,
            bool multithreaded        = false)
        {
            FFMpegHelper.ConversionExceptionCheck(source.ToFileInfo(), output);
            FFMpegHelper.ExtensionExceptionCheck(output, FileExtension.ForType(type));
            FFMpegHelper.ConversionSizeExceptionCheck(source);

            string args = "";

            var height = source.Height * (source.Width / (int)size);

            switch (type)
            {
            case VideoType.Mp4:
                args = Arguments.Input(source) +
                       Arguments.Threads(multithreaded) +
                       Arguments.Scale(size, height) +
                       Arguments.Video(VideoCodec.LibX264, 2400) +
                       Arguments.Speed(speed) +
                       Arguments.Audio(AudioCodec.Aac, audioQuality) +
                       Arguments.Output(output);
                break;

            case VideoType.Ogv:
                args = Arguments.Input(source) +
                       Arguments.Threads(multithreaded) +
                       Arguments.Scale(size, height) +
                       Arguments.Video(VideoCodec.LibTheora, 2400) +
                       Arguments.Speed(16) +
                       Arguments.Audio(AudioCodec.LibVorbis, audioQuality) +
                       Arguments.Output(output);
                break;

            case VideoType.Ts:
                args = Arguments.Input(source) +
                       Arguments.Copy() +
                       Arguments.BitStreamFilter(Channel.Video, Filter.H264_Mp4ToAnnexB) +
                       Arguments.ForceFormat(VideoCodec.MpegTs) +
                       Arguments.Output(output);
                break;
            }

            if (!RunProcess(args, output))
            {
                throw new FFMpegException(FFMpegExceptionType.Conversion, $"The video could not be converted to {Enum.GetName(typeof(VideoType), type)}");
            }

            return(new VideoInfo(output));
        }
示例#4
0
文件: FFMpeg.cs 项目: tub5/FFMpegCore
        /// <summary>
        /// Convert a video do a different format.
        /// </summary>
        /// <param name="source">Input video source.</param>
        /// <param name="output">Output information.</param>
        /// <param name="type">Target conversion video type.</param>
        /// <param name="speed">Conversion target speed/quality (faster speed = lower quality).</param>
        /// <param name="size">Video size.</param>
        /// <param name="audioQuality">Conversion target audio quality.</param>
        /// <param name="multithreaded">Is encoding multithreaded.</param>
        /// <returns>Output video information.</returns>
        public VideoInfo Convert(
            VideoInfo source,
            FileInfo output,
            VideoType type            = VideoType.Mp4,
            Speed speed               = Speed.SuperFast,
            VideoSize size            = VideoSize.Original,
            AudioQuality audioQuality = AudioQuality.Normal,
            bool multithreaded        = false)
        {
            FFMpegHelper.ConversionExceptionCheck(source.ToFileInfo(), output);
            FFMpegHelper.ExtensionExceptionCheck(output, FileExtension.ForType(type));
            FFMpegHelper.ConversionSizeExceptionCheck(source);

            var scale      = VideoSize.Original == size ? 1 : (double)source.Height / (int)size;
            var outputSize = new Size((int)(source.Width / scale), (int)(source.Height / scale));

            if (outputSize.Width % 2 != 0)
            {
                outputSize.Width += 1;
            }

            return(type switch
            {
                VideoType.Mp4 => Convert(new ArgumentContainer(
                                             new InputArgument(source),
                                             new ThreadsArgument(multithreaded),
                                             new ScaleArgument(outputSize),
                                             new VideoCodecArgument(VideoCodec.LibX264, 2400),
                                             new SpeedArgument(speed),
                                             new AudioCodecArgument(AudioCodec.Aac, audioQuality),
                                             new OutputArgument(output))),
                VideoType.Ogv => Convert(new ArgumentContainer(
                                             new InputArgument(source),
                                             new ThreadsArgument(multithreaded),
                                             new ScaleArgument(outputSize),
                                             new VideoCodecArgument(VideoCodec.LibTheora, 2400),
                                             new SpeedArgument(speed),
                                             new AudioCodecArgument(AudioCodec.LibVorbis, audioQuality),
                                             new OutputArgument(output))),
                VideoType.Ts => Convert(new ArgumentContainer(
                                            new InputArgument(source),
                                            new CopyArgument(),
                                            new BitStreamFilterArgument(Channel.Video, Filter.H264_Mp4ToAnnexB),
                                            new ForceFormatArgument(VideoCodec.MpegTs),
                                            new OutputArgument(output))),
                VideoType.WebM => Convert(new ArgumentContainer(
                                              new InputArgument(source),
                                              new ThreadsArgument(multithreaded),
                                              new ScaleArgument(outputSize),
                                              new VideoCodecArgument(VideoCodec.LibVpx, 2400),
                                              new SpeedArgument(speed),
                                              new AudioCodecArgument(AudioCodec.LibVorbis, audioQuality),
                                              new OutputArgument(output))),
                _ => throw new ArgumentOutOfRangeException(nameof(type))
            });
示例#5
0
        /// <summary>
        /// Saves audio from a specific video file to disk.
        /// </summary>
        /// <param name="source">Source video file.</param>
        /// <param name="output">Output audio file.</param>
        /// <returns>Success state.</returns>
        public bool SaveAudio(VideoInfo source, string output)
        {
            _probe.SetVideoInfo(ref source);

            FFMpegHelper.ConversionExceptionCheck(source, output);
            FFMpegHelper.ExtensionExceptionCheck(output, ".mp3");

            string args = string.Format("-i \"{0}\" -vn -ab 256 \"{1}\"", source.Path, output);

            return(_RunProcess(args));
        }
示例#6
0
        /// <summary>
        /// Strips a video file of audio.
        /// </summary>
        /// <param name="source">Source video file.</param>
        /// <param name="output">Output video file.</param>
        /// <returns></returns>
        public bool Mute(VideoInfo source, string output)
        {
            _probe.SetVideoInfo(ref source);

            FFMpegHelper.ConversionExceptionCheck(source, output);
            FFMpegHelper.ExtensionExceptionCheck(output, source.Extension);

            string args = string.Format("-i \"{0}\" -c copy -an \"{1}\"", source.Path, output);

            return(_RunProcess(args));
        }
示例#7
0
        /// <summary>
        /// Adds audio to a video file.
        /// </summary>
        /// <param name="source">Source video file.</param>
        /// <param name="audio">Source audio file.</param>
        /// <param name="output">Output video file.</param>
        /// <param name="stopAtShortest">Indicates if the encoding should stop at the shortest input file.</param>
        /// <returns>Success state</returns>
        public bool AddAudio(VideoInfo source, string audio, string output, bool stopAtShortest = false)
        {
            _probe.SetVideoInfo(ref source);

            FFMpegHelper.ConversionExceptionCheck(source, output);
            FFMpegHelper.InputFilesExistExceptionCheck(audio);
            FFMpegHelper.ExtensionExceptionCheck(output, source.Extension);

            string args = string.Format("-i \"{0}\" -i \"{1}\" -c:v copy -c:a aac -strict experimental {3} \"{2}\"", source.Path, audio, output, stopAtShortest ? "-shortest" : "");

            return(_RunProcess(args));
        }
示例#8
0
        /// <summary>
        ///     Saves audio from a specific video file to disk.
        /// </summary>
        /// <param name="source">Source video file.</param>
        /// <param name="output">Output audio file.</param>
        /// <returns>Success state.</returns>
        public FileInfo ExtractAudio(VideoInfo source, FileInfo output)
        {
            FFMpegHelper.ConversionExceptionCheck(source.ToFileInfo(), output);
            FFMpegHelper.ExtensionExceptionCheck(output, FileExtension.Mp3);

            var args = Arguments.Input(source) +
                       Arguments.Disable(Channel.Video) +
                       Arguments.Output(output);

            if (!RunProcess(args, output))
            {
                throw new FFMpegException(FFMpegExceptionType.Operation, "Could not extract the audio from the requested video.");
            }

            output.Refresh();

            return(output);
        }
示例#9
0
        /// <summary>
        ///     Strips a video file of audio.
        /// </summary>
        /// <param name="source">Source video file.</param>
        /// <param name="output">Output video file.</param>
        /// <returns></returns>
        public VideoInfo Mute(VideoInfo source, FileInfo output)
        {
            FFMpegHelper.ConversionExceptionCheck(source.ToFileInfo(), output);
            FFMpegHelper.ConversionSizeExceptionCheck(source);
            FFMpegHelper.ExtensionExceptionCheck(output, source.Extension);

            var args = Arguments.Input(source) +
                       Arguments.Copy() +
                       Arguments.Disable(Channel.Audio) +
                       Arguments.Output(output);

            if (!RunProcess(args, output))
            {
                throw new FFMpegException(FFMpegExceptionType.Operation, "Could not mute the requested video.");
            }

            return(new VideoInfo(output));
        }
示例#10
0
        /// <summary>
        ///     Strips a video file of audio.
        /// </summary>
        /// <param name="source">Source video file.</param>
        /// <param name="output">Output video file.</param>
        /// <returns></returns>
        public VideoInfo Mute(VideoInfo source, FileInfo output)
        {
            FFMpegHelper.ConversionExceptionCheck(source.ToFileInfo(), output);
            FFMpegHelper.ConversionSizeExceptionCheck(source);
            FFMpegHelper.ExtensionExceptionCheck(output, source.Extension);

            var container = new ArgumentContainer(
                new InputArgument(source),
                new CopyArgument(),
                new DisableChannelArgument(Channel.Audio),
                new OutputArgument(output)
                );

            if (!RunProcess(container, output))
            {
                throw new FFMpegException(FFMpegExceptionType.Operation, "Could not mute the requested video.");
            }

            return(new VideoInfo(output));
        }
示例#11
0
        /// <summary>
        ///     Saves audio from a specific video file to disk.
        /// </summary>
        /// <param name="source">Source video file.</param>
        /// <param name="output">Output audio file.</param>
        /// <returns>Success state.</returns>
        public FileInfo ExtractAudio(VideoInfo source, FileInfo output)
        {
            FFMpegHelper.ConversionExceptionCheck(source.ToFileInfo(), output);
            FFMpegHelper.ExtensionExceptionCheck(output, FileExtension.Mp3);

            var container = new ArgumentContainer(
                new InputArgument(source),
                new DisableChannelArgument(Channel.Video),
                new OutputArgument(output)
                );

            if (!RunProcess(container, output))
            {
                throw new FFMpegException(FFMpegExceptionType.Operation, "Could not extract the audio from the requested video.");
            }

            output.Refresh();

            return(output);
        }
示例#12
0
        /// <summary>
        /// Converts a source video to WebM format.
        /// </summary>
        /// <param name="source">Source video file.</param>
        /// <param name="output">Output video file.</param>
        /// <param name="size">Output video size.</param>
        /// <param name="multithread">Use multithreading for conversion.</param>
        /// <returns>Success state.</returns>
        public bool ToWebM(VideoInfo source, string output, VideoSize size = VideoSize.Original, bool multithread = false)
        {
            _probe.SetVideoInfo(ref source);
            _totalVideoTime = source.Duration;
            IsConverting    = true;

            string threadCount = multithread ?
                                 Environment.ProcessorCount.ToString() : "1",
                   scale = FFMpegHelper.GetScale(size);

            FFMpegHelper.ConversionExceptionCheck(source, output);
            FFMpegHelper.ExtensionExceptionCheck(output, ".webm");

            string conversionArgs = string.Format("-i \"{0}\" -threads {1} {2} -vcodec libvpx -quality good -cpu-used 0 -b:v 1500k -qmin 10 -qmax 42 -maxrate 500k -bufsize 1000k -codec:a libvorbis -b:a 128k \"{3}\"", source.Path,
                                                  threadCount,
                                                  scale,
                                                  output);

            return(_RunProcess(conversionArgs));
        }
示例#13
0
        /// <summary>
        /// Converts a source video to OGV format.
        /// </summary>
        /// <param name="source">Source video file.</param>
        /// <param name="output">Output video file.</param>
        /// <param name="size">Output video size.</param>
        /// <param name="multithread">Use multithreading for conversion.</param>
        /// <returns>Success state.</returns>
        public bool ToOGV(VideoInfo source, string output, VideoSize size = VideoSize.Original, bool multithread = false)
        {
            _probe.SetVideoInfo(ref source);
            _totalVideoTime = source.Duration;
            IsConverting    = true;

            string threadCount = multithread ?
                                 Environment.ProcessorCount.ToString() : "1",
                   scale = FFMpegHelper.GetScale(size);

            FFMpegHelper.ConversionExceptionCheck(source, output);
            FFMpegHelper.ExtensionExceptionCheck(output, ".ogv");

            string conversionArgs = string.Format("-i \"{0}\" -threads {1} {2} -codec:v libtheora -qscale:v 7 -codec:a libvorbis -qscale:a 5 \"{3}\"", source.Path,
                                                  threadCount,
                                                  scale,
                                                  output);

            return(_RunProcess(conversionArgs));
        }
示例#14
0
        /// <summary>
        ///     Adds audio to a video file.
        /// </summary>
        /// <param name="source">Source video file.</param>
        /// <param name="audio">Source audio file.</param>
        /// <param name="output">Output video file.</param>
        /// <param name="stopAtShortest">Indicates if the encoding should stop at the shortest input file.</param>
        /// <returns>Success state</returns>
        public VideoInfo ReplaceAudio(VideoInfo source, FileInfo audio, FileInfo output, bool stopAtShortest = false)
        {
            FFMpegHelper.ConversionExceptionCheck(source.ToFileInfo(), output);
            FFMpegHelper.InputsExistExceptionCheck(audio);
            FFMpegHelper.ConversionSizeExceptionCheck(source);
            FFMpegHelper.ExtensionExceptionCheck(output, source.Extension);

            var args = Arguments.Input(source) +
                       Arguments.Input(audio) +
                       Arguments.Copy(Channel.Video) +
                       Arguments.Audio(AudioCodec.Aac, AudioQuality.Hd) +
                       Arguments.FinalizeAtShortestInput(stopAtShortest) +
                       Arguments.Output(output);

            if (!RunProcess(args, output))
            {
                throw new FFMpegException(FFMpegExceptionType.Operation, "Could not replace the video audio.");
            }

            return(new VideoInfo(output));
        }
示例#15
0
        /// <summary>
        /// Converts a source video to MP4 format.
        /// </summary>
        /// <param name="source">Source video file.</param>
        /// <param name="output">Output video file.</param>
        /// <param name="speed">Conversion speed preset.</param>
        /// <param name="size">Output video size.</param>
        /// <param name="multithread">Use multithreading for conversion.</param>
        /// <returns>Success state.</returns>
        public bool ToMP4(VideoInfo source, string output, Speed speed = Speed.SuperFast, VideoSize size = VideoSize.Original, bool multithread = false)
        {
            _probe.SetVideoInfo(ref source);
            _totalVideoTime = source.Duration;
            IsConverting    = true;

            string threadCount = multithread ?
                                 Environment.ProcessorCount.ToString() : "1",
                   scale = FFMpegHelper.GetScale(size);

            FFMpegHelper.ConversionExceptionCheck(source, output);
            FFMpegHelper.ExtensionExceptionCheck(output, ".mp4");

            string conversionArgs = string.Format("-i \"{0}\" -threads {1} {2} -b:v 2000k -vcodec libx264 -preset {3} -g 30 \"{4}\"", source.Path,
                                                  threadCount,
                                                  scale,
                                                  speed.ToString().ToLower(),
                                                  output);

            return(_RunProcess(conversionArgs));
        }
示例#16
0
        /// <summary>
        ///     Adds audio to a video file.
        /// </summary>
        /// <param name="source">Source video file.</param>
        /// <param name="audio">Source audio file.</param>
        /// <param name="output">Output video file.</param>
        /// <param name="stopAtShortest">Indicates if the encoding should stop at the shortest input file.</param>
        /// <returns>Success state</returns>
        public VideoInfo ReplaceAudio(VideoInfo source, FileInfo audio, FileInfo output, bool stopAtShortest = false)
        {
            FFMpegHelper.ConversionExceptionCheck(source.ToFileInfo(), output);
            FFMpegHelper.InputsExistExceptionCheck(audio);
            FFMpegHelper.ConversionSizeExceptionCheck(source);
            FFMpegHelper.ExtensionExceptionCheck(output, source.Extension);

            var container = new ArgumentContainer(
                new InputArgument(source.FullName, audio.FullName),
                new CopyArgument(),
                new AudioCodecArgument(AudioCodec.Aac, AudioQuality.Hd),
                new ShortestArgument(stopAtShortest),
                new OutputArgument(output)
                );

            if (!RunProcess(container, output))
            {
                throw new FFMpegException(FFMpegExceptionType.Operation, "Could not replace the video audio.");
            }

            return(new VideoInfo(output));
        }
示例#17
0
        /// <summary>
        /// Saves a 'png' thumbnail from the input video.
        /// </summary>
        /// <param name="source">Source video file.</param>
        /// <param name="output">Output video file</param>
        /// <param name="seek">Seek position where the thumbnail should be taken.</param>
        /// <param name="thumbWidth">Thumbnail width.</param>
        /// <param name="thumbHeight">Thumbnail height.</param>
        /// <returns>Success state.</returns>
        public bool SaveThumbnail(VideoInfo source, string output, TimeSpan?seek = null, int thumbWidth = 300, int thumbHeight = 169)
        {
            _probe.SetVideoInfo(ref source);

            if (seek == null)
            {
                seek = new TimeSpan(0, 0, 7);
            }

            FFMpegHelper.ConversionExceptionCheck(source, output);
            FFMpegHelper.ExtensionExceptionCheck(output, ".png");

            string thumbArgs,
                   thumbSize = thumbWidth.ToString() + "x" + thumbHeight.ToString();

            thumbArgs = String.Format("-i \"{0}\" -vcodec png -vframes 1 -ss {1} -s {2} \"{3}\"", source.Path,
                                      seek.ToString(),
                                      thumbSize,
                                      output);

            return(_RunProcess(thumbArgs));
        }
示例#18
0
        /// <summary>
        ///     Saves a 'png' thumbnail from the input video.
        /// </summary>
        /// <param name="source">Source video file.</param>
        /// <param name="output">Output video file</param>
        /// <param name="captureTime">Seek position where the thumbnail should be taken.</param>
        /// <param name="size">Thumbnail size. If width or height equal 0, the other will be computed automatically.</param>
        /// <param name="persistSnapshotOnFileSystem">By default, it deletes the created image on disk. If set to true, it won't delete the image</param>
        /// <returns>Bitmap with the requested snapshot.</returns>
        public Bitmap Snapshot(VideoInfo source, FileInfo output, Size?size = null, TimeSpan?captureTime = null,
                               bool persistSnapshotOnFileSystem             = false)
        {
            if (captureTime == null)
            {
                captureTime = TimeSpan.FromSeconds(source.Duration.TotalSeconds / 3);
            }

            if (output.Extension.ToLower() != FileExtension.Png)
            {
                output = new FileInfo(output.FullName.Replace(output.Extension, FileExtension.Png));
            }

            if (size == null || (size.Value.Height == 0 && size.Value.Width == 0))
            {
                size = new Size(source.Width, source.Height);
            }

            if (size.Value.Width != size.Value.Height)
            {
                if (size.Value.Width == 0)
                {
                    var ratio = source.Width / (double)size.Value.Width;

                    size = new Size((int)(source.Width * ratio), (int)(source.Height * ratio));
                }

                if (size.Value.Height == 0)
                {
                    var ratio = source.Height / (double)size.Value.Height;

                    size = new Size((int)(source.Width * ratio), (int)(source.Height * ratio));
                }
            }

            FFMpegHelper.ConversionExceptionCheck(source.ToFileInfo(), output);
            var container = new ArgumentContainer(
                new InputArgument(source),
                new VideoCodecArgument(VideoCodec.Png),
                new FrameOutputCountArgument(1),
                new SeekArgument(captureTime),
                new SizeArgument(size),
                new OutputArgument(output)
                );

            if (!RunProcess(container, output))
            {
                throw new OperationCanceledException("Could not take snapshot!");
            }

            output.Refresh();

            Bitmap result;

            using (var bmp = (Bitmap)Image.FromFile(output.FullName))
            {
                using var ms = new MemoryStream();
                bmp.Save(ms, ImageFormat.Png);
                result = new Bitmap(ms);
            }

            if (output.Exists && !persistSnapshotOnFileSystem)
            {
                output.Delete();
            }

            return(result);
        }
示例#19
0
        /// <summary>
        /// Convert a video do a different format.
        /// </summary>
        /// <param name="source">Input video source.</param>
        /// <param name="output">Output information.</param>
        /// <param name="type">Target conversion video type.</param>
        /// <param name="speed">Conversion target speed/quality (faster speed = lower quality).</param>
        /// <param name="size">Video size.</param>
        /// <param name="audioQuality">Conversion target audio quality.</param>
        /// <param name="multithreaded">Is encoding multithreaded.</param>
        /// <returns>Output video information.</returns>
        public VideoInfo Convert(
            VideoInfo source,
            FileInfo output,
            VideoType type            = VideoType.Mp4,
            Speed speed               = Speed.SuperFast,
            VideoSize size            = VideoSize.Original,
            AudioQuality audioQuality = AudioQuality.Normal,
            bool multithreaded        = false)
        {
            FFMpegHelper.ConversionExceptionCheck(source.ToFileInfo(), output);
            FFMpegHelper.ExtensionExceptionCheck(output, FileExtension.ForType(type));
            FFMpegHelper.ConversionSizeExceptionCheck(source);

            _totalTime = source.Duration;

            var scale = VideoSize.Original == size ? 1 : (double)source.Height / (int)size;

            var outputSize = new Size(
                (int)(source.Width / scale),
                (int)(source.Height / scale)
                );

            if (outputSize.Width % 2 != 0)
            {
                outputSize.Width += 1;
            }

            var container = new ArgumentContainer();

            switch (type)
            {
            case VideoType.Mp4:
                container.Add(
                    new InputArgument(source),
                    new ThreadsArgument(multithreaded),
                    new ScaleArgument(outputSize),
                    new VideoCodecArgument(VideoCodec.LibX264, 2400),
                    new SpeedArgument(speed),
                    new AudioCodecArgument(AudioCodec.Aac, audioQuality),
                    new OutputArgument(output)
                    );
                break;

            case VideoType.Ogv:
                container.Add(
                    new InputArgument(source),
                    new ThreadsArgument(multithreaded),
                    new ScaleArgument(outputSize),
                    new VideoCodecArgument(VideoCodec.LibTheora, 2400),
                    new SpeedArgument(speed),
                    new AudioCodecArgument(AudioCodec.LibVorbis, audioQuality),
                    new OutputArgument(output)
                    );
                break;

            case VideoType.Ts:
                container.Add(
                    new InputArgument(source),
                    new CopyArgument(),
                    new BitStreamFilterArgument(Channel.Video, Filter.H264_Mp4ToAnnexB),
                    new ForceFormatArgument(VideoCodec.MpegTs),
                    new OutputArgument(output)
                    );
                break;
            }

            if (!RunProcess(container, output))
            {
                throw new FFMpegException(FFMpegExceptionType.Conversion,
                                          $"The video could not be converted to {Enum.GetName(typeof(VideoType), type)}");
            }

            _totalTime = TimeSpan.MinValue;

            return(new VideoInfo(output));
        }