diff --git a/FFMpegCore/FFMpeg/FFMpeg.cs b/FFMpegCore/FFMpeg/FFMpeg.cs
index 820d9fb..282dd88 100644
--- a/FFMpegCore/FFMpeg/FFMpeg.cs
+++ b/FFMpegCore/FFMpeg/FFMpeg.cs
@@ -2,6 +2,7 @@
using FFMpegCore.Enums;
using FFMpegCore.Exceptions;
using FFMpegCore.Helpers;
+using FFMpegCore.Pipes;
using Instances;
namespace FFMpegCore
@@ -32,6 +33,27 @@ public static bool Snapshot(string input, string output, Size? size = null, Time
.OutputToFile(output, true, outputOptions)
.ProcessSynchronously();
}
+
+ ///
+ /// Saves a PNG thumbnail from the input video to the specified output stream.
+ ///
+ /// Input video stream
+ /// Output stream to save the thumbnail
+ /// Thumbnail size. If width or height is set to 0, the other dimension will be computed automatically.
+ /// Seek position where the thumbnail should be taken.
+ /// Index of the selected video stream. If not specified, the primary video stream or the first video stream will be selected.
+ /// Index of the input file
+ /// True if the snapshot was successfully created and saved; otherwise, false.
+ public static bool Snapshot(Stream input, Stream output, Size? size = null, TimeSpan? captureTime = null, int? streamIndex = null, int inputFileIndex = 0)
+ {
+ var source = FFProbe.Analyse(input);
+ var (arguments, outputOptions) = SnapshotArgumentBuilder.BuildSnapshotArguments(input, source, size, captureTime, streamIndex, inputFileIndex);
+
+ return arguments
+ .OutputToPipe(new StreamPipeSink(output), outputOptions)
+ .ProcessSynchronously();
+ }
+
///
/// Saves a 'png' thumbnail from the input video to drive
///
@@ -57,6 +79,26 @@ public static async Task SnapshotAsync(string input, string output, Size?
.ProcessAsynchronously();
}
+ ///
+ /// Saves a PNG thumbnail from the input video to the specified output stream.
+ ///
+ /// Input video stream
+ /// Output stream to save the thumbnail
+ /// Thumbnail size. If width or height is set to 0, the other dimension will be computed automatically.
+ /// Seek position where the thumbnail should be taken.
+ /// Index of the selected video stream. If not specified, the primary video stream or the first video stream will be selected.
+ /// Index of the input file
+ /// True if the snapshot was successfully created and saved; otherwise, false.
+ public static async Task SnapshotAsync(Stream input, Stream output, Size? size = null, TimeSpan? captureTime = null, int? streamIndex = null, int inputFileIndex = 0)
+ {
+ var source = await FFProbe.AnalyseAsync(input).ConfigureAwait(false);
+ var (arguments, outputOptions) = SnapshotArgumentBuilder.BuildSnapshotArguments(input, source, size, captureTime, streamIndex, inputFileIndex);
+
+ return await arguments
+ .OutputToPipe(new StreamPipeSink(output), outputOptions)
+ .ProcessAsynchronously();
+ }
+
public static bool GifSnapshot(string input, string output, Size? size = null, TimeSpan? captureTime = null, TimeSpan? duration = null, int? streamIndex = null)
{
if (Path.GetExtension(output)?.ToLower() != FileExtension.Gif)
diff --git a/FFMpegCore/FFMpeg/SnapshotArgumentBuilder.cs b/FFMpegCore/FFMpeg/SnapshotArgumentBuilder.cs
index 0d9b414..eafe57b 100644
--- a/FFMpegCore/FFMpeg/SnapshotArgumentBuilder.cs
+++ b/FFMpegCore/FFMpeg/SnapshotArgumentBuilder.cs
@@ -2,6 +2,7 @@
using System.Drawing;
using FFMpegCore.Enums;
+using FFMpegCore.Pipes;
namespace FFMpegCore;
@@ -31,13 +32,38 @@ public static (FFMpegArguments, Action outputOptions) Bui
.Resize(size));
}
+ public static (FFMpegArguments, Action outputOptions) BuildSnapshotArguments(
+ Stream inputStream,
+ IMediaAnalysis source,
+ Size? size = null,
+ TimeSpan? captureTime = null,
+ int? streamIndex = null,
+ int inputFileIndex = 0)
+ {
+ captureTime ??= TimeSpan.FromSeconds(source.Duration.TotalSeconds / 3);
+ size = PrepareSnapshotSize(source, size);
+ streamIndex ??= source.PrimaryVideoStream?.Index
+ ?? source.VideoStreams.FirstOrDefault()?.Index
+ ?? 0;
+
+ return (FFMpegArguments
+ .FromPipeInput(new StreamPipeSource(inputStream), options => options
+ .Seek(captureTime)),
+ options => options
+ .SelectStream((int)streamIndex, inputFileIndex)
+ .WithVideoCodec(VideoCodec.Png)
+ .WithFrameOutputCount(1)
+ .Resize(size)
+ );
+ }
+
public static (FFMpegArguments, Action outputOptions) BuildGifSnapshotArguments(
- string input,
- IMediaAnalysis source,
- Size? size = null,
- TimeSpan? captureTime = null,
- TimeSpan? duration = null,
- int? streamIndex = null,
+ string input,
+ IMediaAnalysis source,
+ Size? size = null,
+ TimeSpan? captureTime = null,
+ TimeSpan? duration = null,
+ int? streamIndex = null,
int fps = 12)
{
var defaultGifOutputSize = new Size(480, -1);