/// <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( IMediaAnalysis source, string output, ContainerFormat format, Speed speed = Speed.SuperFast, VideoSize size = VideoSize.Original, AudioQuality audioQuality = AudioQuality.Normal, bool multithreaded = false) { FFMpegHelper.ExtensionExceptionCheck(output, format.Extension); 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 .FromInputFiles(true, source.Path) .UsingMultithreading(multithreaded) .WithVideoCodec(VideoCodec.LibX264) .WithVideoBitrate(2400) .Scale(outputSize) .WithSpeedPreset(speed) .WithAudioCodec(AudioCodec.Aac) .WithAudioBitrate(audioQuality) .OutputToFile(output) .ProcessSynchronously(), "ogv" => FFMpegArguments .FromInputFiles(true, source.Path) .UsingMultithreading(multithreaded) .WithVideoCodec(VideoCodec.LibTheora) .WithVideoBitrate(2400) .Scale(outputSize) .WithSpeedPreset(speed) .WithAudioCodec(AudioCodec.LibVorbis) .WithAudioBitrate(audioQuality) .OutputToFile(output) .ProcessSynchronously(), "mpegts" => FFMpegArguments .FromInputFiles(true, source.Path) .CopyChannel() .WithBitStreamFilter(Channel.Video, Filter.H264_Mp4ToAnnexB) .ForceFormat(VideoType.Ts) .OutputToFile(output) .ProcessSynchronously(), "webm" => FFMpegArguments .FromInputFiles(true, source.Path) .UsingMultithreading(multithreaded) .WithVideoCodec(VideoCodec.LibVpx) .WithVideoBitrate(2400) .Scale(outputSize) .WithSpeedPreset(speed) .WithAudioCodec(AudioCodec.LibVorbis) .WithAudioBitrate(audioQuality) .OutputToFile(output) .ProcessSynchronously(), _ => throw new ArgumentOutOfRangeException(nameof(format)) });
/// <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, 15000), new SpeedArgument(speed), new AudioCodecArgument(AudioCodec.Aac), new OverrideArgument(), 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)); }