Esempio n. 1
0
        /// <summary>
        /// Converts an image sequence to a video.
        /// </summary>
        /// <param name="output">Output video file.</param>
        /// <param name="frameRate">FPS</param>
        /// <param name="images">Image sequence collection</param>
        /// <returns>Output video information.</returns>
        public VideoInfo JoinImageSequence(FileInfo output, double frameRate = 30, params ImageInfo[] images)
        {
            var temporaryImageFiles = images.Select((image, index) =>
            {
                FFMpegHelper.ConversionSizeExceptionCheck(Image.FromFile(image.FullName));
                var destinationPath = image.FullName.Replace(image.Name, $"{index.ToString().PadLeft(9, '0')}{image.Extension}");
                File.Copy(image.FullName, destinationPath);

                return(destinationPath);
            }).ToList();

            var firstImage = images.First();

            var args = Arguments.FrameRate(frameRate) +
                       Arguments.Size(new Size(firstImage.Width, firstImage.Height)) +
                       Arguments.StartNumber(0) +
                       Arguments.Input($"{firstImage.Directory}\\%09d.png") +
                       Arguments.FrameOutputCount(images.Length) +
                       Arguments.Video(VideoCodec.LibX264) +
                       Arguments.Output(output);

            try
            {
                if (!RunProcess(args, output))
                {
                    throw new FFMpegException(FFMpegExceptionType.Operation, "Could not join the provided image sequence.");
                }

                return(new VideoInfo(output));
            }
            finally
            {
                Cleanup(temporaryImageFiles);
            }
        }
Esempio n. 2
0
        /// <summary>
        ///     Joins a list of video files.
        /// </summary>
        /// <param name="output">Output video file.</param>
        /// <param name="videos">List of vides that need to be joined together.</param>
        /// <returns>Output video information.</returns>
        public VideoInfo Join(FileInfo output, params VideoInfo[] videos)
        {
            FFMpegHelper.OutputExistsExceptionCheck(output);
            FFMpegHelper.InputsExistExceptionCheck(videos.Select(video => video.ToFileInfo()).ToArray());

            var temporaryVideoParts = videos.Select(video =>
            {
                FFMpegHelper.ConversionSizeExceptionCheck(video);
                var destinationPath = video.FullName.Replace(video.Extension, FileExtension.Ts);
                Convert(
                    video,
                    new FileInfo(destinationPath),
                    VideoType.Ts
                    );
                return(destinationPath);
            }).ToList();

            var args = Arguments.InputConcat(temporaryVideoParts) +
                       Arguments.Copy() +
                       Arguments.BitStreamFilter(Channel.Audio, Filter.Aac_AdtstoAsc) +
                       Arguments.Output(output);

            try
            {
                if (!RunProcess(args, output))
                {
                    throw new FFMpegException(FFMpegExceptionType.Operation, "Could not join the provided video files.");
                }
                return(new VideoInfo(output));
            }
            finally
            {
                Cleanup(temporaryVideoParts);
            }
        }
Esempio n. 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));
        }
Esempio n. 4
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);

            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))
            });
Esempio n. 5
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));
        }
Esempio n. 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 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));
        }
Esempio n. 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 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));
        }
Esempio n. 8
0
        /// <summary>
        ///     Adds a poster image to an audio file.
        /// </summary>
        /// <param name="image">Source image file.</param>
        /// <param name="audio">Source audio file.</param>
        /// <param name="output">Output video file.</param>
        /// <returns></returns>
        public VideoInfo PosterWithAudio(FileInfo image, FileInfo audio, FileInfo output)
        {
            FFMpegHelper.InputsExistExceptionCheck(image, audio);
            FFMpegHelper.ExtensionExceptionCheck(output, FileExtension.Mp4);
            FFMpegHelper.ConversionSizeExceptionCheck(Image.FromFile(image.FullName));

            var args = Arguments.Loop(1) +
                       Arguments.Input(image) +
                       Arguments.Input(audio) +
                       Arguments.Video(VideoCodec.LibX264, 2400) +
                       Arguments.Audio(AudioCodec.Aac, AudioQuality.Normal) +
                       Arguments.FinalizeAtShortestInput(true) +
                       Arguments.Output(output);

            if (!RunProcess(args, output))
            {
                throw new FFMpegException(FFMpegExceptionType.Operation, "An error occured while adding the audio file to the image.");
            }

            return(new VideoInfo(output));
        }
Esempio n. 9
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));
        }
Esempio n. 10
0
        /// <summary>
        ///     Adds a poster image to an audio file.
        /// </summary>
        /// <param name="image">Source image file.</param>
        /// <param name="audio">Source audio file.</param>
        /// <param name="output">Output video file.</param>
        /// <returns></returns>
        public VideoInfo PosterWithAudio(FileInfo image, FileInfo audio, FileInfo output)
        {
            FFMpegHelper.InputsExistExceptionCheck(image, audio);
            FFMpegHelper.ExtensionExceptionCheck(output, FileExtension.Mp4);
            FFMpegHelper.ConversionSizeExceptionCheck(Image.FromFile(image.FullName));

            var container = new ArgumentContainer(
                new LoopArgument(1),
                new InputArgument(image.FullName, audio.FullName),
                new VideoCodecArgument(VideoCodec.LibX264, 2400),
                new AudioCodecArgument(AudioCodec.Aac, AudioQuality.Normal),
                new ShortestArgument(true),
                new OutputArgument(output)
                );

            if (!RunProcess(container, output))
            {
                throw new FFMpegException(FFMpegExceptionType.Operation, "An error occured while adding the audio file to the image.");
            }

            return(new VideoInfo(output));
        }
Esempio n. 11
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 static bool Convert(
            string input,
            string output,
            ContainerFormat format,
            Speed speed               = Speed.SuperFast,
            VideoSize size            = VideoSize.Original,
            AudioQuality audioQuality = AudioQuality.Normal,
            bool multithreaded        = false)
        {
            FFMpegHelper.ExtensionExceptionCheck(output, format.Extension);
            var source = FFProbe.Analyse(input);

            FFMpegHelper.ConversionSizeExceptionCheck(source);

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

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

            return(format.Name switch
            {
                "mp4" => FFMpegArguments
                .FromFileInput(input)
                .OutputToFile(output, true, options => options
                              .UsingMultithreading(multithreaded)
                              .WithVideoCodec(VideoCodec.LibX264)
                              .WithVideoBitrate(2400)
                              .WithVideoFilters(filterOptions => filterOptions
                                                .Scale(outputSize))
                              .WithSpeedPreset(speed)
                              .WithAudioCodec(AudioCodec.Aac)
                              .WithAudioBitrate(audioQuality))
                .ProcessSynchronously(),
                "ogv" => FFMpegArguments
                .FromFileInput(input)
                .OutputToFile(output, true, options => options
                              .UsingMultithreading(multithreaded)
                              .WithVideoCodec(VideoCodec.LibTheora)
                              .WithVideoBitrate(2400)
                              .WithVideoFilters(filterOptions => filterOptions
                                                .Scale(outputSize))
                              .WithSpeedPreset(speed)
                              .WithAudioCodec(AudioCodec.LibVorbis)
                              .WithAudioBitrate(audioQuality))
                .ProcessSynchronously(),
                "mpegts" => FFMpegArguments
                .FromFileInput(input)
                .OutputToFile(output, true, options => options
                              .CopyChannel()
                              .WithBitStreamFilter(Channel.Video, Filter.H264_Mp4ToAnnexB)
                              .ForceFormat(VideoType.Ts))
                .ProcessSynchronously(),
                "webm" => FFMpegArguments
                .FromFileInput(input)
                .OutputToFile(output, true, options => options
                              .UsingMultithreading(multithreaded)
                              .WithVideoCodec(VideoCodec.LibVpx)
                              .WithVideoBitrate(2400)
                              .WithVideoFilters(filterOptions => filterOptions
                                                .Scale(outputSize))
                              .WithSpeedPreset(speed)
                              .WithAudioCodec(AudioCodec.LibVorbis)
                              .WithAudioBitrate(audioQuality))
                .ProcessSynchronously(),
                _ => throw new ArgumentOutOfRangeException(nameof(format))
            });
Esempio n. 12
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));
        }