/// <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> /// <returns>Bitmap with the requested snapshot.</returns> public Bitmap Snapshot(VideoInfo source, FileInfo output, Size?size = null, TimeSpan?captureTime = null) { 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 thumbArgs = ArgumentsStringifier.Input(source) + ArgumentsStringifier.Video(VideoCodec.Png) + ArgumentsStringifier.FrameOutputCount(1) + ArgumentsStringifier.Seek(captureTime) + ArgumentsStringifier.Size(size) + ArgumentsStringifier.Output(output); if (!RunProcess(thumbArgs, 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) { output.Delete(); } return(result); }