diff --git a/FFMpegCore.Test/FFProbeTests.cs b/FFMpegCore.Test/FFProbeTests.cs index 2ee5a92..ba1c869 100644 --- a/FFMpegCore.Test/FFProbeTests.cs +++ b/FFMpegCore.Test/FFProbeTests.cs @@ -30,6 +30,19 @@ public class FFProbeTests Assert.IsTrue(frameAnalysis.Frames.All(f => f.MediaType == "video")); } + [TestMethod] + public void FrameAnalysis_FromStream_Sync() + { + using var stream = File.OpenRead(TestResources.WebmVideo); + var frameAnalysis = FFProbe.GetFrames(stream); + + Assert.HasCount(90, frameAnalysis.Frames); + Assert.IsTrue(frameAnalysis.Frames.All(f => f.PixelFormat == "yuv420p")); + Assert.IsTrue(frameAnalysis.Frames.All(f => f.Height == 360)); + Assert.IsTrue(frameAnalysis.Frames.All(f => f.Width == 640)); + Assert.IsTrue(frameAnalysis.Frames.All(f => f.MediaType == "video")); + } + [TestMethod] public async Task FrameAnalysis_Async() { @@ -42,6 +55,19 @@ public class FFProbeTests Assert.IsTrue(frameAnalysis.Frames.All(f => f.MediaType == "video")); } + [TestMethod] + public async Task FrameAnalysis_FromStream_Async() + { + using var stream = File.OpenRead(TestResources.WebmVideo); + var frameAnalysis = await FFProbe.GetFramesAsync(stream, cancellationToken: TestContext.CancellationToken); + + Assert.HasCount(90, frameAnalysis.Frames); + Assert.IsTrue(frameAnalysis.Frames.All(f => f.PixelFormat == "yuv420p")); + Assert.IsTrue(frameAnalysis.Frames.All(f => f.Height == 360)); + Assert.IsTrue(frameAnalysis.Frames.All(f => f.Width == 640)); + Assert.IsTrue(frameAnalysis.Frames.All(f => f.MediaType == "video")); + } + [TestMethod] public async Task PacketAnalysis_Async() { diff --git a/FFMpegCore/FFProbe/FFProbe.cs b/FFMpegCore/FFProbe/FFProbe.cs index 164ea72..a263b45 100644 --- a/FFMpegCore/FFProbe/FFProbe.cs +++ b/FFMpegCore/FFProbe/FFProbe.cs @@ -22,6 +22,11 @@ public static class FFProbe return ParseOutput(result); } + public static FFProbeFrames GetFrames(Stream stream, FFOptions? ffOptions = null, string? customArguments = null) + { + return GetFramesAsync(stream, ffOptions, CancellationToken.None, customArguments).ConfigureAwait(false).GetAwaiter().GetResult(); + } + public static FFProbeFrames GetFrames(string filePath, FFOptions? ffOptions = null, string? customArguments = null) { ThrowIfInputFileDoesNotExist(filePath); @@ -167,6 +172,31 @@ public static class FFProbe return ParseFramesOutput(result); } + public static async Task GetFramesAsync(Stream stream, FFOptions? ffOptions = null, CancellationToken cancellationToken = default, + string? customArguments = null) + { + var streamPipeSource = new StreamPipeSource(stream); + var pipeArgument = new InputPipeArgument(streamPipeSource); + var instance = PrepareFrameAnalysisInstance(pipeArgument.PipePath, ffOptions ?? GlobalFFOptions.Current, customArguments); + pipeArgument.Pre(); + + var task = instance.Start().WaitForExitAsync(cancellationToken); + try + { + await pipeArgument.During(cancellationToken).ConfigureAwait(false); + } + catch (IOException) { } + finally + { + pipeArgument.Post(); + } + + var result = task.ConfigureAwait(false).GetAwaiter().GetResult(); + ThrowIfExitCodeNotZero(result); + + return ParseFramesOutput(result); + } + private static IMediaAnalysis ParseOutput(IProcessResult instance) { var json = string.Join(string.Empty, instance.OutputData);