/// <summary> /// Saves a 'png' thumbnail from the input video to drive /// </summary> /// <param name="input">Source video analysis</param> /// <param name="output">Output video file path</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="streamIndex">Selected video stream index.</param> /// <param name="inputFileIndex">Input file index</param> /// <returns>Bitmap with the requested snapshot.</returns> public static async Task <bool> SnapshotAsync(string input, string output, Size?size = null, TimeSpan?captureTime = null, int?streamIndex = null, int inputFileIndex = 0) { if (Path.GetExtension(output) != FileExtension.Png) { output = Path.GetFileNameWithoutExtension(output) + FileExtension.Png; } var source = await FFProbe.AnalyseAsync(input); var(arguments, outputOptions) = BuildSnapshotArguments(input, source, size, captureTime, streamIndex, inputFileIndex); return(await arguments .OutputToFile(output, true, outputOptions) .ProcessAsynchronously()); }
/// <summary> /// Saves a 'png' thumbnail to an in-memory bitmap /// </summary> /// <param name="input">Source 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="streamIndex">Selected video stream index.</param> /// <param name="inputFileIndex">Input file index</param> /// <returns>Bitmap with the requested snapshot.</returns> public static async Task <Bitmap> SnapshotAsync(string input, Size?size = null, TimeSpan?captureTime = null, int?streamIndex = null, int inputFileIndex = 0) { var source = await FFProbe.AnalyseAsync(input); var(arguments, outputOptions) = BuildSnapshotArguments(input, source, size, captureTime, streamIndex, inputFileIndex); using var ms = new MemoryStream(); await arguments .OutputToPipe(new StreamPipeSink(ms), options => outputOptions(options .ForceFormat("rawvideo"))) .ProcessAsynchronously(); ms.Position = 0; return(new Bitmap(ms)); }
/// <summary> /// Saves a 'png' thumbnail from the input video to drive /// </summary> /// <param name="input">Source video analysis</param> /// <param name="output">Output video file path</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> /// <returns>Bitmap with the requested snapshot.</returns> public static bool Snapshot(string input, string output, Size?size = null, TimeSpan?captureTime = null) { if (Path.GetExtension(output) != FileExtension.Png) { output = Path.GetFileNameWithoutExtension(output) + FileExtension.Png; } var source = FFProbe.Analyse(input); var(arguments, outputOptions) = BuildSnapshotArguments(input, source, size, captureTime); return(arguments .OutputToFile(output, true, outputOptions) .ProcessSynchronously()); }
/// <summary> /// Saves a 'png' thumbnail to an in-memory bitmap /// </summary> /// <param name="input">Source 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="streamIndex">Selected video stream index.</param> /// <param name="inputFileIndex">Input file index</param> /// <returns>Bitmap with the requested snapshot.</returns> public static Bitmap Snapshot(string input, Size?size = null, TimeSpan?captureTime = null, int?streamIndex = null, int inputFileIndex = 0) { var source = FFProbe.Analyse(input); var(arguments, outputOptions) = BuildSnapshotArguments(input, source, size, captureTime, streamIndex, inputFileIndex); using var ms = new MemoryStream(); arguments .OutputToPipe(new StreamPipeSink(ms), options => outputOptions(options .ForceFormat("rawvideo"))) .ProcessSynchronously(); ms.Position = 0; using var bitmap = new Bitmap(ms); return(bitmap.Clone(new Rectangle(0, 0, bitmap.Width, bitmap.Height), bitmap.PixelFormat)); }
/// <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)) });