/// <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 = ArgumentsStringifier.FrameRate(frameRate) + ArgumentsStringifier.Size(new Size(firstImage.Width, firstImage.Height)) + ArgumentsStringifier.StartNumber(0) + ArgumentsStringifier.Input($"{firstImage.Directory}\\%09d.png") + ArgumentsStringifier.FrameOutputCount(images.Length) + ArgumentsStringifier.Video(VideoCodec.LibX264) + ArgumentsStringifier.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); } }
/// <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); }