diff --git a/FFMpegCore.Test/VideoTest.cs b/FFMpegCore.Test/VideoTest.cs
index ffa5da3..8101123 100644
--- a/FFMpegCore.Test/VideoTest.cs
+++ b/FFMpegCore.Test/VideoTest.cs
@@ -3,6 +3,7 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
+using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
@@ -427,7 +428,7 @@ public void Video_ToOGV_MultiThread()
}
[TestMethod]
- public void Video_Snapshot()
+ public void Video_Snapshot_InMemory()
{
var output = Input.OutputLocation(ImageType.Png);
@@ -435,7 +436,7 @@ public void Video_Snapshot()
{
var input = FFProbe.Analyse(Input.FullName);
- using var bitmap = FFMpeg.Snapshot(input, output);
+ using var bitmap = FFMpeg.Snapshot(input);
Assert.AreEqual(input.PrimaryVideoStream.Width, bitmap.Width);
Assert.AreEqual(input.PrimaryVideoStream.Height, bitmap.Height);
Assert.AreEqual(bitmap.RawFormat, ImageFormat.Png);
@@ -455,11 +456,12 @@ public void Video_Snapshot_PersistSnapshot()
{
var input = FFProbe.Analyse(Input.FullName);
- using var bitmap = FFMpeg.Snapshot(input, output, persistSnapshotOnFileSystem: true);
+ FFMpeg.Snapshot(input, output);
+
+ var bitmap = Image.FromFile(output);
Assert.AreEqual(input.PrimaryVideoStream.Width, bitmap.Width);
Assert.AreEqual(input.PrimaryVideoStream.Height, bitmap.Height);
Assert.AreEqual(bitmap.RawFormat, ImageFormat.Png);
- Assert.IsTrue(File.Exists(output));
}
finally
{
diff --git a/FFMpegCore/FFMpeg/FFMpeg.cs b/FFMpegCore/FFMpeg/FFMpeg.cs
index 13d141f..8bcdc1f 100644
--- a/FFMpegCore/FFMpeg/FFMpeg.cs
+++ b/FFMpegCore/FFMpeg/FFMpeg.cs
@@ -7,29 +7,68 @@
using FFMpegCore.Enums;
using FFMpegCore.Exceptions;
using FFMpegCore.Helpers;
+using FFMpegCore.Pipes;
namespace FFMpegCore
{
public static class FFMpeg
{
///
- /// Saves a 'png' thumbnail from the input video.
+ /// Saves a 'png' thumbnail from the input video to drive
///
- /// Source video file.
- /// Output video file
+ /// Source video analysis
+ /// Output video file path
/// Seek position where the thumbnail should be taken.
/// Thumbnail size. If width or height equal 0, the other will be computed automatically.
- /// By default, it deletes the created image on disk. If set to true, it won't delete the image
/// Bitmap with the requested snapshot.
- public static Bitmap Snapshot(MediaAnalysis source, string output, Size? size = null, TimeSpan? captureTime = null,
- bool persistSnapshotOnFileSystem = false)
+ public static bool Snapshot(MediaAnalysis source, string output, Size? size = null, TimeSpan? captureTime = null)
{
- if (captureTime == null)
- captureTime = TimeSpan.FromSeconds(source.Duration.TotalSeconds / 3);
+ captureTime ??= TimeSpan.FromSeconds(source.Duration.TotalSeconds / 3);
if (Path.GetExtension(output) != FileExtension.Png)
output = Path.GetFileNameWithoutExtension(output) + FileExtension.Png;
+ size = PrepareSnapshotSize(source, size);
+
+ return FFMpegArguments
+ .FromInputFiles(source.Path)
+ .WithVideoCodec(VideoCodec.Png)
+ .WithFrameOutputCount(1)
+ .Resize(size)
+ .Seek(captureTime)
+ .OutputToFile(output)
+ .ProcessSynchronously();
+ }
+ ///
+ /// Saves a 'png' thumbnail to an in-memory bitmap
+ ///
+ /// Source video file.
+ /// Seek position where the thumbnail should be taken.
+ /// Thumbnail size. If width or height equal 0, the other will be computed automatically.
+ /// Bitmap with the requested snapshot.
+ public static Bitmap Snapshot(MediaAnalysis source, Size? size = null, TimeSpan? captureTime = null)
+ {
+ captureTime ??= TimeSpan.FromSeconds(source.Duration.TotalSeconds / 3);
+
+ size = PrepareSnapshotSize(source, size);
+
+ using var ms = new MemoryStream();
+ FFMpegArguments
+ .FromInputFiles(source.Path)
+ .WithVideoCodec(VideoCodec.Png)
+ .WithFrameOutputCount(1)
+ .Resize(size)
+ .Seek(captureTime)
+ .ForceFormat("rawvideo")
+ .OutputToPipe(new StreamPipeDataReader(ms))
+ .ProcessSynchronously();
+
+ ms.Position = 0;
+ return new Bitmap(ms);
+ }
+
+ private static Size? PrepareSnapshotSize(MediaAnalysis source, Size? size)
+ {
if (size == null || (size.Value.Height == 0 && size.Value.Width == 0))
size = new Size(source.PrimaryVideoStream.Width, source.PrimaryVideoStream.Height);
@@ -37,44 +76,22 @@ public static Bitmap Snapshot(MediaAnalysis source, string output, Size? size =
{
if (size.Value.Width == 0)
{
- var ratio = source.PrimaryVideoStream.Width / (double)size.Value.Width;
+ var ratio = source.PrimaryVideoStream.Width / (double) size.Value.Width;
- size = new Size((int)(source.PrimaryVideoStream.Width * ratio), (int)(source.PrimaryVideoStream.Height * ratio));
+ size = new Size((int) (source.PrimaryVideoStream.Width * ratio),
+ (int) (source.PrimaryVideoStream.Height * ratio));
}
if (size.Value.Height == 0)
{
- var ratio = source.PrimaryVideoStream.Height / (double)size.Value.Height;
+ var ratio = source.PrimaryVideoStream.Height / (double) size.Value.Height;
- size = new Size((int)(source.PrimaryVideoStream.Width * ratio), (int)(source.PrimaryVideoStream.Height * ratio));
+ size = new Size((int) (source.PrimaryVideoStream.Width * ratio),
+ (int) (source.PrimaryVideoStream.Height * ratio));
}
}
- var success = FFMpegArguments
- .FromInputFiles(true, source.Path)
- .WithVideoCodec(VideoCodec.Png)
- .WithFrameOutputCount(1)
- .Resize(size)
- .Seek(captureTime)
- .OutputToFile(output)
- .ProcessSynchronously();
-
-
- if (!success)
- throw new OperationCanceledException("Could not take snapshot!");
-
- Bitmap result;
- using (var bmp = (Bitmap)Image.FromFile(output))
- {
- using var ms = new MemoryStream();
- bmp.Save(ms, ImageFormat.Png);
- result = new Bitmap(ms);
- }
-
- if (File.Exists(output) && !persistSnapshotOnFileSystem)
- File.Delete(output);
-
- return result;
+ return size;
}
///
@@ -489,7 +506,7 @@ public static bool TryGetContainerFormat(string name, out ContainerFormat fmt)
return FFMpegCache.ContainerFormats.TryGetValue(name, out fmt);
}
- public static ContainerFormat GetContinerFormat(string name)
+ public static ContainerFormat GetContainerFormat(string name)
{
if (TryGetContainerFormat(name, out var fmt))
return fmt;