diff --git a/FFMpegCore.Test/ArgumentBuilderTest.cs b/FFMpegCore.Test/ArgumentBuilderTest.cs index f4dbfe9..de625e2 100644 --- a/FFMpegCore.Test/ArgumentBuilderTest.cs +++ b/FFMpegCore.Test/ArgumentBuilderTest.cs @@ -6,7 +6,7 @@ namespace FFMpegCore.Test { [TestClass] - public class ArgumentBuilderTest : BaseTest + public class ArgumentBuilderTest { private readonly string[] _concatFiles = { "1.mp4", "2.mp4", "3.mp4", "4.mp4"}; diff --git a/FFMpegCore.Test/AudioTest.cs b/FFMpegCore.Test/AudioTest.cs index 552ca24..378b7f7 100644 --- a/FFMpegCore.Test/AudioTest.cs +++ b/FFMpegCore.Test/AudioTest.cs @@ -3,80 +3,60 @@ using FFMpegCore.Test.Resources; using Microsoft.VisualStudio.TestTools.UnitTesting; using System.IO; +using System.Linq; namespace FFMpegCore.Test { [TestClass] - public class AudioTest : BaseTest + public class AudioTest { [TestMethod] public void Audio_Remove() { - var output = Input.OutputLocation(VideoType.Mp4); - - try - { - FFMpeg.Mute(Input.FullName, output); - Assert.IsTrue(File.Exists(output)); - } - finally - { - if (File.Exists(output)) File.Delete(output); - } + using var outputFile = new TemporaryFile("out.mp4"); + + FFMpeg.Mute(TestResources.Mp4Video, outputFile); + var analysis = FFProbe.Analyse(outputFile); + + Assert.IsTrue(analysis.VideoStreams.Any()); + Assert.IsTrue(!analysis.AudioStreams.Any()); } [TestMethod] public void Audio_Save() { - var output = Input.OutputLocation(AudioType.Mp3); - - try - { - FFMpeg.ExtractAudio(Input.FullName, output); - Assert.IsTrue(File.Exists(output)); - } - finally - { - if (File.Exists(output)) File.Delete(output); - } + using var outputFile = new TemporaryFile("out.mp3"); + + FFMpeg.ExtractAudio(TestResources.Mp4Video, outputFile); + var analysis = FFProbe.Analyse(outputFile); + + Assert.IsTrue(!analysis.VideoStreams.Any()); + Assert.IsTrue(analysis.AudioStreams.Any()); } [TestMethod] public void Audio_Add() { - var output = Input.OutputLocation(VideoType.Mp4); - try - { - var success = FFMpeg.ReplaceAudio(VideoLibrary.LocalVideoNoAudio.FullName, VideoLibrary.LocalAudio.FullName, output); - Assert.IsTrue(success); - var audioAnalysis = FFProbe.Analyse(VideoLibrary.LocalVideoNoAudio.FullName); - var videoAnalysis = FFProbe.Analyse(VideoLibrary.LocalAudio.FullName); - var outputAnalysis = FFProbe.Analyse(output); - Assert.AreEqual(Math.Max(videoAnalysis.Duration.TotalSeconds, audioAnalysis.Duration.TotalSeconds), outputAnalysis.Duration.TotalSeconds, 0.15); - Assert.IsTrue(File.Exists(output)); - } - finally - { - if (File.Exists(output)) File.Delete(output); - } + using var outputFile = new TemporaryFile("out.mp4"); + + var success = FFMpeg.ReplaceAudio(TestResources.Mp4WithoutAudio, TestResources.Mp3Audio, outputFile); + var videoAnalysis = FFProbe.Analyse(TestResources.Mp4WithoutAudio); + var audioAnalysis = FFProbe.Analyse(TestResources.Mp3Audio); + var outputAnalysis = FFProbe.Analyse(outputFile); + + Assert.IsTrue(success); + Assert.AreEqual(Math.Max(videoAnalysis.Duration.TotalSeconds, audioAnalysis.Duration.TotalSeconds), outputAnalysis.Duration.TotalSeconds, 0.15); + Assert.IsTrue(File.Exists(outputFile)); } [TestMethod] public void Image_AddAudio() { - var output = Input.OutputLocation(VideoType.Mp4); - - try - { - FFMpeg.PosterWithAudio(VideoLibrary.LocalCover.FullName, VideoLibrary.LocalAudio.FullName, output); - var analysis = FFProbe.Analyse(VideoLibrary.LocalAudio.FullName); - Assert.IsTrue(analysis.Duration.TotalSeconds > 0); - Assert.IsTrue(File.Exists(output)); - } - finally - { - if (File.Exists(output)) File.Delete(output); - } + using var outputFile = new TemporaryFile("out.mp4"); + FFMpeg.PosterWithAudio(TestResources.PngImage, TestResources.Mp3Audio, outputFile); + var analysis = FFProbe.Analyse(TestResources.Mp3Audio); + Assert.IsTrue(analysis.Duration.TotalSeconds > 0); + Assert.IsTrue(File.Exists(outputFile)); } } } \ No newline at end of file diff --git a/FFMpegCore.Test/BaseTest.cs b/FFMpegCore.Test/BaseTest.cs deleted file mode 100644 index 38a5bcc..0000000 --- a/FFMpegCore.Test/BaseTest.cs +++ /dev/null @@ -1,15 +0,0 @@ -using FFMpegCore.Test.Resources; -using System.IO; - -namespace FFMpegCore.Test -{ - public class BaseTest - { - protected FileInfo Input; - - public BaseTest() - { - Input = VideoLibrary.LocalVideo; - } - } -} \ No newline at end of file diff --git a/FFMpegCore.Test/FFProbeTests.cs b/FFMpegCore.Test/FFProbeTests.cs index 7fe928e..fe5f9f9 100644 --- a/FFMpegCore.Test/FFProbeTests.cs +++ b/FFMpegCore.Test/FFProbeTests.cs @@ -11,16 +11,26 @@ public class FFProbeTests [TestMethod] public void Probe_TooLongOutput() { - Assert.ThrowsException(() => FFProbe.Analyse(VideoLibrary.LocalVideo.FullName, 5)); + Assert.ThrowsException(() => FFProbe.Analyse(TestResources.Mp4Video, 5)); + } + + + [TestMethod] + public async Task Audio_FromStream_Duration() + { + var fileAnalysis = await FFProbe.AnalyseAsync(TestResources.Mp4Video); + await using var inputStream = File.OpenRead(TestResources.Mp4Video); + var streamAnalysis = await FFProbe.AnalyseAsync(inputStream); + Assert.IsTrue(fileAnalysis.Duration == streamAnalysis.Duration); } [TestMethod] public void Probe_Success() { - var info = FFProbe.Analyse(VideoLibrary.LocalVideo.FullName); + var info = FFProbe.Analyse(TestResources.Mp4Video); Assert.AreEqual(3, info.Duration.Seconds); Assert.AreEqual(".mp4", info.Extension); - Assert.AreEqual(VideoLibrary.LocalVideo.FullName, info.Path); + Assert.AreEqual(TestResources.Mp4Video, info.Path); Assert.AreEqual("5.1", info.PrimaryAudioStream.ChannelLayout); Assert.AreEqual(6, info.PrimaryAudioStream.Channels); @@ -47,14 +57,14 @@ public void Probe_Success() [TestMethod, Timeout(10000)] public async Task Probe_Async_Success() { - var info = await FFProbe.AnalyseAsync(VideoLibrary.LocalVideo.FullName); + var info = await FFProbe.AnalyseAsync(TestResources.Mp4Video); Assert.AreEqual(3, info.Duration.Seconds); } [TestMethod, Timeout(10000)] public void Probe_Success_FromStream() { - using var stream = File.OpenRead(VideoLibrary.LocalVideoWebm.FullName); + using var stream = File.OpenRead(TestResources.WebmVideo); var info = FFProbe.Analyse(stream); Assert.AreEqual(3, info.Duration.Seconds); } @@ -62,7 +72,7 @@ public void Probe_Success_FromStream() [TestMethod, Timeout(10000)] public async Task Probe_Success_FromStream_Async() { - await using var stream = File.OpenRead(VideoLibrary.LocalVideoWebm.FullName); + await using var stream = File.OpenRead(TestResources.WebmVideo); var info = await FFProbe.AnalyseAsync(stream); Assert.AreEqual(3, info.Duration.Seconds); } diff --git a/FFMpegCore.Test/Resources/TestResources.cs b/FFMpegCore.Test/Resources/TestResources.cs new file mode 100644 index 0000000..765df38 --- /dev/null +++ b/FFMpegCore.Test/Resources/TestResources.cs @@ -0,0 +1,27 @@ +using System; +using System.IO; +using FFMpegCore.Enums; + +namespace FFMpegCore.Test.Resources +{ + public enum AudioType + { + Mp3 + } + + public enum ImageType + { + Png + } + + public static class TestResources + { + public static readonly string Mp4Video = "./Resources/input_3sec.mp4"; + public static readonly string WebmVideo = "./Resources/input_3sec.webm"; + public static readonly string Mp4WithoutVideo = "./Resources/input_audio_only_10sec.mp4"; + public static readonly string Mp4WithoutAudio = "./Resources/input_video_only_3sec.mp4"; + public static readonly string Mp3Audio = "./Resources/audio.mp3"; + public static readonly string PngImage = "./Resources/cover.png"; + public static readonly string ImageCollection = "./Resources/images"; + } +} diff --git a/FFMpegCore.Test/Resources/VideoLibrary.cs b/FFMpegCore.Test/Resources/VideoLibrary.cs deleted file mode 100644 index 8bb0139..0000000 --- a/FFMpegCore.Test/Resources/VideoLibrary.cs +++ /dev/null @@ -1,51 +0,0 @@ -using System; -using System.IO; -using FFMpegCore.Enums; - -namespace FFMpegCore.Test.Resources -{ - public enum AudioType - { - Mp3 - } - - public enum ImageType - { - Png - } - - public static class VideoLibrary - { - public static readonly FileInfo LocalVideo = new FileInfo($".{Path.DirectorySeparatorChar}Resources{Path.DirectorySeparatorChar}input_3sec.mp4"); - public static readonly FileInfo LocalVideoWebm = new FileInfo($".{Path.DirectorySeparatorChar}Resources{Path.DirectorySeparatorChar}input_3sec.webm"); - public static readonly FileInfo LocalVideoAudioOnly = new FileInfo($".{Path.DirectorySeparatorChar}Resources{Path.DirectorySeparatorChar}input_audio_only_10sec.mp4"); - public static readonly FileInfo LocalVideoNoAudio = new FileInfo($".{Path.DirectorySeparatorChar}Resources{Path.DirectorySeparatorChar}input_video_only_3sec.mp4"); - public static readonly FileInfo LocalAudio = new FileInfo($".{Path.DirectorySeparatorChar}Resources{Path.DirectorySeparatorChar}audio.mp3"); - public static readonly FileInfo LocalCover = new FileInfo($".{Path.DirectorySeparatorChar}Resources{Path.DirectorySeparatorChar}cover.png"); - public static readonly FileInfo ImageDirectory = new FileInfo($".{Path.DirectorySeparatorChar}Resources{Path.DirectorySeparatorChar}images"); - public static readonly FileInfo ImageJoinOutput = new FileInfo($".{Path.DirectorySeparatorChar}Resources{Path.DirectorySeparatorChar}images{Path.DirectorySeparatorChar}output.mp4"); - - public static string OutputLocation(this FileInfo file, ContainerFormat type) - { - return OutputLocation(file, type.Extension, "_converted"); - } - - public static string OutputLocation(this FileInfo file, AudioType type) - { - return OutputLocation(file, type.ToString(), "_audio"); - } - - public static string OutputLocation(this FileInfo file, ImageType type) - { - return OutputLocation(file, type.ToString(), "_screenshot"); - } - - public static string OutputLocation(this FileInfo file, string type, string keyword) - { - string originalLocation = file.Directory.FullName, - outputFile = file.Name.Replace(file.Extension, keyword + "." + type.ToLowerInvariant()); - - return $"{originalLocation}{Path.DirectorySeparatorChar}{Guid.NewGuid()}_{outputFile}"; - } - } -} diff --git a/FFMpegCore.Test/TemporaryFile.cs b/FFMpegCore.Test/TemporaryFile.cs new file mode 100644 index 0000000..f64f5fe --- /dev/null +++ b/FFMpegCore.Test/TemporaryFile.cs @@ -0,0 +1,22 @@ +using System; +using System.IO; + +namespace FFMpegCore.Test +{ + public class TemporaryFile : IDisposable + { + private readonly string _path; + + public TemporaryFile(string filename) + { + _path = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid()}-{filename}"); + } + + public static implicit operator string(TemporaryFile temporaryFile) => temporaryFile._path; + public void Dispose() + { + if (File.Exists(_path)) + File.Delete(_path); + } + } +} \ No newline at end of file diff --git a/FFMpegCore.Test/VideoTest.cs b/FFMpegCore.Test/VideoTest.cs index f4553ef..b2bff02 100644 --- a/FFMpegCore.Test/VideoTest.cs +++ b/FFMpegCore.Test/VideoTest.cs @@ -15,105 +15,90 @@ namespace FFMpegCore.Test { [TestClass] - public class VideoTest : BaseTest + public class VideoTest { public bool Convert(ContainerFormat type, bool multithreaded = false, VideoSize size = VideoSize.Original) { - var output = Input.OutputLocation(type); + using var outputFile = new TemporaryFile($"out{type.Extension}"); - try + var input = FFProbe.Analyse(TestResources.Mp4Video); + FFMpeg.Convert(input, outputFile, type, size: size, multithreaded: multithreaded); + var outputVideo = FFProbe.Analyse(outputFile); + + Assert.IsTrue(File.Exists(outputFile)); + Assert.AreEqual(outputVideo.Duration.TotalSeconds, input.Duration.TotalSeconds, 0.1); + if (size == VideoSize.Original) { - var input = FFProbe.Analyse(Input.FullName); - FFMpeg.Convert(input, output, type, size: size, multithreaded: multithreaded); - var outputVideo = FFProbe.Analyse(output); + Assert.AreEqual(outputVideo.PrimaryVideoStream.Width, input.PrimaryVideoStream.Width); + Assert.AreEqual(outputVideo.PrimaryVideoStream.Height, input.PrimaryVideoStream.Height); + } + else + { + Assert.AreNotEqual(outputVideo.PrimaryVideoStream.Width, input.PrimaryVideoStream.Width); + Assert.AreNotEqual(outputVideo.PrimaryVideoStream.Height, input.PrimaryVideoStream.Height); + Assert.AreEqual(outputVideo.PrimaryVideoStream.Height, (int)size); + } - Assert.IsTrue(File.Exists(output)); - Assert.AreEqual(outputVideo.Duration.TotalSeconds, input.Duration.TotalSeconds, 0.1); - if (size == VideoSize.Original) - { - Assert.AreEqual(outputVideo.PrimaryVideoStream.Width, input.PrimaryVideoStream.Width); - Assert.AreEqual(outputVideo.PrimaryVideoStream.Height, input.PrimaryVideoStream.Height); - } - else - { - Assert.AreNotEqual(outputVideo.PrimaryVideoStream.Width, input.PrimaryVideoStream.Width); - Assert.AreNotEqual(outputVideo.PrimaryVideoStream.Height, input.PrimaryVideoStream.Height); - Assert.AreEqual(outputVideo.PrimaryVideoStream.Height, (int)size); - } - return File.Exists(output) && - outputVideo.Duration == input.Duration && + return File.Exists(outputFile) && + outputVideo.Duration == input.Duration && + ( ( - ( size == VideoSize.Original && outputVideo.PrimaryVideoStream.Width == input.PrimaryVideoStream.Width && outputVideo.PrimaryVideoStream.Height == input.PrimaryVideoStream.Height - ) || - ( + ) || + ( size != VideoSize.Original && outputVideo.PrimaryVideoStream.Width != input.PrimaryVideoStream.Width && outputVideo.PrimaryVideoStream.Height != input.PrimaryVideoStream.Height && outputVideo.PrimaryVideoStream.Height == (int)size - ) - ); - } - finally - { - if (File.Exists(output)) - File.Delete(output); - } + ) + ); } private void ConvertFromStreamPipe(ContainerFormat type, params IArgument[] arguments) { - var output = Input.OutputLocation(type); + using var outputFile = new TemporaryFile($"out{type.Extension}"); + + var input = FFProbe.Analyse(TestResources.WebmVideo); + using var inputStream = File.OpenRead(input.Path); + var processor = FFMpegArguments + .FromPipeInput(new StreamPipeSource(inputStream)) + .OutputToFile(outputFile, false, opt => + { + foreach (var arg in arguments) + opt.WithArgument(arg); + }); - try + var scaling = arguments.OfType().FirstOrDefault(); + + var success = processor.ProcessSynchronously(); + + var outputVideo = FFProbe.Analyse(outputFile); + + Assert.IsTrue(success); + Assert.IsTrue(File.Exists(outputFile)); + Assert.IsTrue(Math.Abs((outputVideo.Duration - input.Duration).TotalMilliseconds) < 1000.0 / input.PrimaryVideoStream.FrameRate); + + if (scaling?.Size == null) { - var input = FFProbe.Analyse(VideoLibrary.LocalVideoWebm.FullName); - using var inputStream = File.OpenRead(input.Path); - var processor = FFMpegArguments - .FromPipeInput(new StreamPipeSource(inputStream)) - .OutputToFile(output, false, opt => - { - foreach (var arg in arguments) - opt.WithArgument(arg); - }); - - var scaling = arguments.OfType().FirstOrDefault(); - - var success = processor.ProcessSynchronously(); - - var outputVideo = FFProbe.Analyse(output); - - Assert.IsTrue(success); - Assert.IsTrue(File.Exists(output)); - Assert.IsTrue(Math.Abs((outputVideo.Duration - input.Duration).TotalMilliseconds) < 1000.0 / input.PrimaryVideoStream.FrameRate); - - if (scaling?.Size == null) - { - Assert.AreEqual(outputVideo.PrimaryVideoStream.Width, input.PrimaryVideoStream.Width); - Assert.AreEqual(outputVideo.PrimaryVideoStream.Height, input.PrimaryVideoStream.Height); - } - else - { - if (scaling.Size.Value.Width != -1) - { - Assert.AreEqual(outputVideo.PrimaryVideoStream.Width, scaling.Size.Value.Width); - } - - if (scaling.Size.Value.Height != -1) - { - Assert.AreEqual(outputVideo.PrimaryVideoStream.Height, scaling.Size.Value.Height); - } - - Assert.AreNotEqual(outputVideo.PrimaryVideoStream.Width, input.PrimaryVideoStream.Width); - Assert.AreNotEqual(outputVideo.PrimaryVideoStream.Height, input.PrimaryVideoStream.Height); - } + Assert.AreEqual(outputVideo.PrimaryVideoStream.Width, input.PrimaryVideoStream.Width); + Assert.AreEqual(outputVideo.PrimaryVideoStream.Height, input.PrimaryVideoStream.Height); } - finally + else { - if (File.Exists(output)) - File.Delete(output); + if (scaling.Size.Value.Width != -1) + { + Assert.AreEqual(outputVideo.PrimaryVideoStream.Width, scaling.Size.Value.Width); + } + + if (scaling.Size.Value.Height != -1) + { + Assert.AreEqual(outputVideo.PrimaryVideoStream.Height, scaling.Size.Value.Height); + } + + Assert.AreNotEqual(outputVideo.PrimaryVideoStream.Width, input.PrimaryVideoStream.Width); + Assert.AreNotEqual(outputVideo.PrimaryVideoStream.Height, input.PrimaryVideoStream.Height); } } @@ -121,7 +106,7 @@ private void ConvertToStreamPipe(params IArgument[] arguments) { using var ms = new MemoryStream(); var processor = FFMpegArguments - .FromFileInput(VideoLibrary.LocalVideo) + .FromFileInput(TestResources.Mp4Video) .OutputToPipe(new StreamPipeSink(ms), opt => { foreach (var arg in arguments) @@ -135,7 +120,7 @@ private void ConvertToStreamPipe(params IArgument[] arguments) ms.Position = 0; var outputVideo = FFProbe.Analyse(ms); - var input = FFProbe.Analyse(VideoLibrary.LocalVideo.FullName); + var input = FFProbe.Analyse(TestResources.Mp4Video); // Assert.IsTrue(Math.Abs((outputVideo.Duration - input.Duration).TotalMilliseconds) < 1000.0 / input.PrimaryVideoStream.FrameRate); if (scaling?.Size == null) @@ -162,53 +147,45 @@ private void ConvertToStreamPipe(params IArgument[] arguments) public void Convert(ContainerFormat type, Action validationMethod, params IArgument[] arguments) { - var output = Input.OutputLocation(type); + using var outputFile = new TemporaryFile($"out{type.Extension}"); - try - { - var input = FFProbe.Analyse(Input.FullName); + var input = FFProbe.Analyse(TestResources.Mp4Video); - var processor = FFMpegArguments - .FromFileInput(VideoLibrary.LocalVideo) - .OutputToFile(output, false, opt => + var processor = FFMpegArguments + .FromFileInput(TestResources.Mp4Video) + .OutputToFile(outputFile, false, opt => { foreach (var arg in arguments) opt.WithArgument(arg); }); - var scaling = arguments.OfType().FirstOrDefault(); - processor.ProcessSynchronously(); + var scaling = arguments.OfType().FirstOrDefault(); + processor.ProcessSynchronously(); - var outputVideo = FFProbe.Analyse(output); + var outputVideo = FFProbe.Analyse(outputFile); - Assert.IsTrue(File.Exists(output)); - Assert.AreEqual(outputVideo.Duration.TotalSeconds, input.Duration.TotalSeconds, 0.1); - validationMethod?.Invoke(outputVideo); - if (scaling?.Size == null) - { - Assert.AreEqual(outputVideo.PrimaryVideoStream.Width, input.PrimaryVideoStream.Width); - Assert.AreEqual(outputVideo.PrimaryVideoStream.Height, input.PrimaryVideoStream.Height); - } - else - { - if (scaling.Size.Value.Width != -1) - { - Assert.AreEqual(outputVideo.PrimaryVideoStream.Width, scaling.Size.Value.Width); - } - - if (scaling.Size.Value.Height != -1) - { - Assert.AreEqual(outputVideo.PrimaryVideoStream.Height, scaling.Size.Value.Height); - } - - Assert.AreNotEqual(outputVideo.PrimaryVideoStream.Width, input.PrimaryVideoStream.Width); - Assert.AreNotEqual(outputVideo.PrimaryVideoStream.Height, input.PrimaryVideoStream.Height); - } - } - finally + Assert.IsTrue(File.Exists(outputFile)); + Assert.AreEqual(outputVideo.Duration.TotalSeconds, input.Duration.TotalSeconds, 0.1); + validationMethod?.Invoke(outputVideo); + if (scaling?.Size == null) { - if (File.Exists(output)) - File.Delete(output); + Assert.AreEqual(outputVideo.PrimaryVideoStream.Width, input.PrimaryVideoStream.Width); + Assert.AreEqual(outputVideo.PrimaryVideoStream.Height, input.PrimaryVideoStream.Height); + } + else + { + if (scaling.Size.Value.Width != -1) + { + Assert.AreEqual(outputVideo.PrimaryVideoStream.Width, scaling.Size.Value.Width); + } + + if (scaling.Size.Value.Height != -1) + { + Assert.AreEqual(outputVideo.PrimaryVideoStream.Height, scaling.Size.Value.Height); + } + + Assert.AreNotEqual(outputVideo.PrimaryVideoStream.Width, input.PrimaryVideoStream.Width); + Assert.AreNotEqual(outputVideo.PrimaryVideoStream.Height, input.PrimaryVideoStream.Height); } } @@ -219,50 +196,41 @@ public void Convert(ContainerFormat type, params IArgument[] inputArguments) public void ConvertFromPipe(ContainerFormat type, System.Drawing.Imaging.PixelFormat fmt, params IArgument[] arguments) { - var output = Input.OutputLocation(type); + using var outputFile = new TemporaryFile($"out{type.Extension}"); - try + var videoFramesSource = new RawVideoPipeSource(BitmapSource.CreateBitmaps(128, fmt, 256, 256)); + var processor = FFMpegArguments.FromPipeInput(videoFramesSource).OutputToFile(outputFile, false, opt => { - var videoFramesSource = new RawVideoPipeSource(BitmapSource.CreateBitmaps(128, fmt, 256, 256)); - var processor = FFMpegArguments.FromPipeInput(videoFramesSource).OutputToFile(output, false, opt => - { - foreach (var arg in arguments) - opt.WithArgument(arg); - }); - var scaling = arguments.OfType().FirstOrDefault(); - processor.ProcessSynchronously(); + foreach (var arg in arguments) + opt.WithArgument(arg); + }); + var scaling = arguments.OfType().FirstOrDefault(); + processor.ProcessSynchronously(); - var outputVideo = FFProbe.Analyse(output); + var outputVideo = FFProbe.Analyse(outputFile); - Assert.IsTrue(File.Exists(output)); + Assert.IsTrue(File.Exists(outputFile)); - if (scaling?.Size == null) - { - Assert.AreEqual(outputVideo.PrimaryVideoStream.Width, videoFramesSource.Width); - Assert.AreEqual(outputVideo.PrimaryVideoStream.Height, videoFramesSource.Height); - } - else - { - if (scaling.Size.Value.Width != -1) - { - Assert.AreEqual(outputVideo.PrimaryVideoStream.Width, scaling.Size.Value.Width); - } - - if (scaling.Size.Value.Height != -1) - { - Assert.AreEqual(outputVideo.PrimaryVideoStream.Height, scaling.Size.Value.Height); - } - - Assert.AreNotEqual(outputVideo.PrimaryVideoStream.Width, videoFramesSource.Width); - Assert.AreNotEqual(outputVideo.PrimaryVideoStream.Height, videoFramesSource.Height); - } - } - finally + if (scaling?.Size == null) { - if (File.Exists(output)) - File.Delete(output); + Assert.AreEqual(outputVideo.PrimaryVideoStream.Width, videoFramesSource.Width); + Assert.AreEqual(outputVideo.PrimaryVideoStream.Height, videoFramesSource.Height); } + else + { + if (scaling.Size.Value.Width != -1) + { + Assert.AreEqual(outputVideo.PrimaryVideoStream.Width, scaling.Size.Value.Width); + } + if (scaling.Size.Value.Height != -1) + { + Assert.AreEqual(outputVideo.PrimaryVideoStream.Height, scaling.Size.Value.Height); + } + + Assert.AreNotEqual(outputVideo.PrimaryVideoStream.Width, videoFramesSource.Width); + Assert.AreNotEqual(outputVideo.PrimaryVideoStream.Height, videoFramesSource.Height); + } } [TestMethod, Timeout(10000)] @@ -287,7 +255,6 @@ public void Video_ToMP4_Args() [DataTestMethod, Timeout(10000)] [DataRow(System.Drawing.Imaging.PixelFormat.Format24bppRgb)] [DataRow(System.Drawing.Imaging.PixelFormat.Format32bppArgb)] - // [DataRow(PixelFormat.Format48bppRgb)] public void Video_ToMP4_Args_Pipe(System.Drawing.Imaging.PixelFormat pixelFormat) { ConvertFromPipe(VideoType.Mp4, pixelFormat, new VideoCodecArgument(VideoCodec.LibX264)); @@ -307,7 +274,7 @@ await Assert.ThrowsExceptionAsync(async () => await using var ms = new MemoryStream(); var pipeSource = new StreamPipeSink(ms); await FFMpegArguments - .FromFileInput(VideoLibrary.LocalVideo) + .FromFileInput(TestResources.Mp4Video) .OutputToPipe(pipeSource, opt => opt.ForceFormat("mkv")) .ProcessAsynchronously(); }); @@ -315,14 +282,12 @@ await FFMpegArguments [TestMethod, Timeout(10000)] public void Video_StreamFile_OutputToMemoryStream() { - // using var input = File.OpenRead(VideoLibrary.LocalVideo.FullName); var output = new MemoryStream(); FFMpegArguments - // .FromFileInput(VideoLibrary.LocalVideo.FullName) - .FromPipeInput(new StreamPipeSource(File.OpenRead(VideoLibrary.LocalVideoWebm.FullName)), options => options.ForceFormat("webm")) + .FromPipeInput(new StreamPipeSource(File.OpenRead(TestResources.WebmVideo)), options => options.ForceFormat("webm")) .OutputToPipe(new StreamPipeSink(output), options => options - .ForceFormat("mp4")) + .ForceFormat("mpegts")) .ProcessSynchronously(); output.Position = 0; @@ -343,7 +308,7 @@ public void Video_ToMP4_Args_StreamOutputPipe_Async() using var ms = new MemoryStream(); var pipeSource = new StreamPipeSink(ms); FFMpegArguments - .FromFileInput(VideoLibrary.LocalVideo) + .FromFileInput(TestResources.Mp4Video) .OutputToPipe(pipeSource, opt => opt .WithVideoCodec(VideoCodec.LibX264) .ForceFormat("matroska")) @@ -354,11 +319,11 @@ public void Video_ToMP4_Args_StreamOutputPipe_Async() [TestMethod, Timeout(10000)] public async Task TestDuplicateRun() { - FFMpegArguments.FromFileInput(VideoLibrary.LocalVideo) + FFMpegArguments.FromFileInput(TestResources.Mp4Video) .OutputToFile("temporary.mp4") .ProcessSynchronously(); - await FFMpegArguments.FromFileInput(VideoLibrary.LocalVideo) + await FFMpegArguments.FromFileInput(TestResources.Mp4Video) .OutputToFile("temporary.mp4") .ProcessAsynchronously(); @@ -389,7 +354,6 @@ public void Video_ToTS_Args() [DataTestMethod, Timeout(10000)] [DataRow(System.Drawing.Imaging.PixelFormat.Format24bppRgb)] [DataRow(System.Drawing.Imaging.PixelFormat.Format32bppArgb)] - // [DataRow(PixelFormat.Format48bppRgb)] public void Video_ToTS_Args_Pipe(System.Drawing.Imaging.PixelFormat pixelFormat) { ConvertFromPipe(VideoType.Ts, pixelFormat, new ForceFormatArgument(VideoType.Ts)); @@ -464,190 +428,126 @@ public void Video_ToOGV_MultiThread() [TestMethod, Timeout(10000)] public void Video_Snapshot_InMemory() { - var output = Input.OutputLocation(ImageType.Png); - - try - { - var input = FFProbe.Analyse(Input.FullName); - - 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); - } - finally - { - if (File.Exists(output)) - File.Delete(output); - } + var input = FFProbe.Analyse(TestResources.Mp4Video); + 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); } [TestMethod, Timeout(10000)] public void Video_Snapshot_PersistSnapshot() { - var output = Input.OutputLocation(ImageType.Png); - try - { - var input = FFProbe.Analyse(Input.FullName); + var outputPath = new TemporaryFile("out.png"); + var input = FFProbe.Analyse(TestResources.Mp4Video); - FFMpeg.Snapshot(input, output); + FFMpeg.Snapshot(input, outputPath); - 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); - bitmap.Dispose(); - } - finally - { - if (File.Exists(output)) - File.Delete(output); - } + using var bitmap = Image.FromFile(outputPath); + Assert.AreEqual(input.PrimaryVideoStream.Width, bitmap.Width); + Assert.AreEqual(input.PrimaryVideoStream.Height, bitmap.Height); + Assert.AreEqual(bitmap.RawFormat, ImageFormat.Png); } [TestMethod, Timeout(10000)] public void Video_Join() { - var output = Input.OutputLocation(VideoType.Mp4); - var newInput = Input.OutputLocation(VideoType.Mp4.Name, "duplicate"); - try - { - var input = FFProbe.Analyse(Input.FullName); - File.Copy(Input.FullName, newInput); - - var success = FFMpeg.Join(output, Input.FullName, newInput); - Assert.IsTrue(success); - - Assert.IsTrue(File.Exists(output)); - var expectedDuration = input.Duration * 2; - var result = FFProbe.Analyse(output); - Assert.AreEqual(expectedDuration.Days, result.Duration.Days); - Assert.AreEqual(expectedDuration.Hours, result.Duration.Hours); - Assert.AreEqual(expectedDuration.Minutes, result.Duration.Minutes); - Assert.AreEqual(expectedDuration.Seconds, result.Duration.Seconds); - Assert.AreEqual(input.PrimaryVideoStream.Height, result.PrimaryVideoStream.Height); - Assert.AreEqual(input.PrimaryVideoStream.Width, result.PrimaryVideoStream.Width); - } - finally - { - if (File.Exists(output)) - File.Delete(output); - - if (File.Exists(newInput)) - File.Delete(newInput); - } + var inputCopy = new TemporaryFile("copy-input.mp4"); + File.Copy(TestResources.Mp4Video, inputCopy); + var outputPath = new TemporaryFile("out.mp4"); + var input = FFProbe.Analyse(TestResources.Mp4Video); + var success = FFMpeg.Join(outputPath, TestResources.Mp4Video, inputCopy); + Assert.IsTrue(success); + Assert.IsTrue(File.Exists(outputPath)); + + var expectedDuration = input.Duration * 2; + var result = FFProbe.Analyse(outputPath); + Assert.AreEqual(expectedDuration.Days, result.Duration.Days); + Assert.AreEqual(expectedDuration.Hours, result.Duration.Hours); + Assert.AreEqual(expectedDuration.Minutes, result.Duration.Minutes); + Assert.AreEqual(expectedDuration.Seconds, result.Duration.Seconds); + Assert.AreEqual(input.PrimaryVideoStream.Height, result.PrimaryVideoStream.Height); + Assert.AreEqual(input.PrimaryVideoStream.Width, result.PrimaryVideoStream.Width); } [TestMethod, Timeout(10000)] public void Video_Join_Image_Sequence() { - try - { - var imageSet = new List(); - Directory.EnumerateFiles(VideoLibrary.ImageDirectory.FullName) - .Where(file => file.ToLower().EndsWith(".png")) - .ToList() - .ForEach(file => - { - for (var i = 0; i < 15; i++) - { - imageSet.Add(new ImageInfo(file)); - } - }); - - var success = FFMpeg.JoinImageSequence(VideoLibrary.ImageJoinOutput.FullName, images: imageSet.ToArray()); - Assert.IsTrue(success); - var result = FFProbe.Analyse(VideoLibrary.ImageJoinOutput.FullName); - - VideoLibrary.ImageJoinOutput.Refresh(); - - Assert.IsTrue(VideoLibrary.ImageJoinOutput.Exists); - Assert.AreEqual(3, result.Duration.Seconds); - Assert.AreEqual(imageSet.First().Width, result.PrimaryVideoStream.Width); - Assert.AreEqual(imageSet.First().Height, result.PrimaryVideoStream.Height); - } - finally - { - VideoLibrary.ImageJoinOutput.Refresh(); - if (VideoLibrary.ImageJoinOutput.Exists) + var imageSet = new List(); + Directory.EnumerateFiles(TestResources.ImageCollection) + .Where(file => file.ToLower().EndsWith(".png")) + .ToList() + .ForEach(file => { - VideoLibrary.ImageJoinOutput.Delete(); - } - } + for (var i = 0; i < 15; i++) + { + imageSet.Add(new ImageInfo(file)); + } + }); + + var outputFile = new TemporaryFile("out.mp4"); + var success = FFMpeg.JoinImageSequence(outputFile, images: imageSet.ToArray()); + Assert.IsTrue(success); + var result = FFProbe.Analyse(outputFile); + Assert.AreEqual(3, result.Duration.Seconds); + Assert.AreEqual(imageSet.First().Width, result.PrimaryVideoStream.Width); + Assert.AreEqual(imageSet.First().Height, result.PrimaryVideoStream.Height); } [TestMethod, Timeout(10000)] public void Video_With_Only_Audio_Should_Extract_Metadata() { - var video = FFProbe.Analyse(VideoLibrary.LocalVideoAudioOnly.FullName); + var video = FFProbe.Analyse(TestResources.Mp4WithoutVideo); Assert.AreEqual(null, video.PrimaryVideoStream); Assert.AreEqual("aac", video.PrimaryAudioStream.CodecName); Assert.AreEqual(10, video.Duration.TotalSeconds, 0.5); - // Assert.AreEqual(1.25, video.Size); } [TestMethod, Timeout(10000)] public void Video_Duration() { - var video = FFProbe.Analyse(VideoLibrary.LocalVideo.FullName); - var output = Input.OutputLocation(VideoType.Mp4); + var video = FFProbe.Analyse(TestResources.Mp4Video); + var outputFile = new TemporaryFile("out.mp4"); - try - { - FFMpegArguments - .FromFileInput(VideoLibrary.LocalVideo) - .OutputToFile(output, false, opt => opt.WithDuration(TimeSpan.FromSeconds(video.Duration.TotalSeconds - 2))) - .ProcessSynchronously(); + FFMpegArguments + .FromFileInput(TestResources.Mp4Video) + .OutputToFile(outputFile, false, opt => opt.WithDuration(TimeSpan.FromSeconds(video.Duration.TotalSeconds - 2))) + .ProcessSynchronously(); - Assert.IsTrue(File.Exists(output)); - var outputVideo = FFProbe.Analyse(output); + Assert.IsTrue(File.Exists(outputFile)); + var outputVideo = FFProbe.Analyse(outputFile); - Assert.AreEqual(video.Duration.Days, outputVideo.Duration.Days); - Assert.AreEqual(video.Duration.Hours, outputVideo.Duration.Hours); - Assert.AreEqual(video.Duration.Minutes, outputVideo.Duration.Minutes); - Assert.AreEqual(video.Duration.Seconds - 2, outputVideo.Duration.Seconds); - } - finally - { - if (File.Exists(output)) - File.Delete(output); - } + Assert.AreEqual(video.Duration.Days, outputVideo.Duration.Days); + Assert.AreEqual(video.Duration.Hours, outputVideo.Duration.Hours); + Assert.AreEqual(video.Duration.Minutes, outputVideo.Duration.Minutes); + Assert.AreEqual(video.Duration.Seconds - 2, outputVideo.Duration.Seconds); } [TestMethod, Timeout(10000)] public void Video_UpdatesProgress() { - var output = Input.OutputLocation(VideoType.Mp4); + var outputFile = new TemporaryFile("out.mp4"); var percentageDone = 0.0; var timeDone = TimeSpan.Zero; void OnPercentageProgess(double percentage) => percentageDone = percentage; void OnTimeProgess(TimeSpan time) => timeDone = time; - var analysis = FFProbe.Analyse(VideoLibrary.LocalVideo.FullName); + var analysis = FFProbe.Analyse(TestResources.Mp4Video); + var success = FFMpegArguments + .FromFileInput(TestResources.Mp4Video) + .OutputToFile(outputFile, false, opt => opt + .WithDuration(TimeSpan.FromSeconds(2))) + .NotifyOnProgress(OnPercentageProgess, analysis.Duration) + .NotifyOnProgress(OnTimeProgess) + .ProcessSynchronously(); - - try - { - var success = FFMpegArguments - .FromFileInput(VideoLibrary.LocalVideo) - .OutputToFile(output, false, opt => opt - .WithDuration(TimeSpan.FromSeconds(2))) - .NotifyOnProgress(OnPercentageProgess, analysis.Duration) - .NotifyOnProgress(OnTimeProgess) - .ProcessSynchronously(); - - Assert.IsTrue(success); - Assert.IsTrue(File.Exists(output)); - Assert.AreNotEqual(0.0, percentageDone); - Assert.AreNotEqual(TimeSpan.Zero, timeDone); - } - finally - { - if (File.Exists(output)) - File.Delete(output); - } + Assert.IsTrue(success); + Assert.IsTrue(File.Exists(outputFile)); + Assert.AreNotEqual(0.0, percentageDone); + Assert.AreNotEqual(TimeSpan.Zero, timeDone); } [TestMethod, Timeout(10000)] @@ -673,11 +573,11 @@ public void Video_TranscodeInMemory() [TestMethod, Timeout(10000)] public async Task Video_Cancel_Async() { - var output = Input.OutputLocation(VideoType.Mp4); + var outputFile = new TemporaryFile("out.mp4"); var task = FFMpegArguments - .FromFileInput(VideoLibrary.LocalVideo) - .OutputToFile(output, false, opt => opt + .FromFileInput(TestResources.Mp4Video) + .OutputToFile(outputFile, false, opt => opt .Resize(new Size(1000, 1000)) .WithAudioCodec(AudioCodec.Aac) .WithVideoCodec(VideoCodec.LibX264) @@ -687,19 +587,11 @@ public async Task Video_Cancel_Async() .CancellableThrough(out var cancel) .ProcessAsynchronously(false); - try - { - await Task.Delay(300); - cancel(); + await Task.Delay(300); + cancel(); - var result = await task; - Assert.IsFalse(result); - } - finally - { - if (File.Exists(output)) - File.Delete(output); - } + var result = await task; + Assert.IsFalse(result); } } } diff --git a/FFMpegCore/FFMpeg/Enums/ContainerFormat.cs b/FFMpegCore/FFMpeg/Enums/ContainerFormat.cs index 8c046ac..37c2bda 100644 --- a/FFMpegCore/FFMpeg/Enums/ContainerFormat.cs +++ b/FFMpegCore/FFMpeg/Enums/ContainerFormat.cs @@ -4,7 +4,7 @@ namespace FFMpegCore.Enums { public class ContainerFormat { - private static readonly Regex _formatRegex = new Regex(@"([D ])([E ])\s+([a-z0-9_]+)\s+(.+)"); + private static readonly Regex FormatRegex = new Regex(@"([D ])([E ])\s+([a-z0-9_]+)\s+(.+)"); public string Name { get; private set; } public bool DemuxingSupported { get; private set; } @@ -27,17 +27,19 @@ internal ContainerFormat(string name) internal static bool TryParse(string line, out ContainerFormat fmt) { - var match = _formatRegex.Match(line); + var match = FormatRegex.Match(line); if (!match.Success) { fmt = null!; return false; } - fmt = new ContainerFormat(match.Groups[3].Value); - fmt.DemuxingSupported = match.Groups[1].Value == " "; - fmt.MuxingSupported = match.Groups[2].Value == " "; - fmt.Description = match.Groups[4].Value; + fmt = new ContainerFormat(match.Groups[3].Value) + { + DemuxingSupported = match.Groups[1].Value == " ", + MuxingSupported = match.Groups[2].Value == " ", + Description = match.Groups[4].Value + }; return true; } } diff --git a/FFMpegCore/FFMpeg/FFMpegArgumentProcessor.cs b/FFMpegCore/FFMpeg/FFMpegArgumentProcessor.cs index 424b598..ba53a48 100644 --- a/FFMpegCore/FFMpeg/FFMpegArgumentProcessor.cs +++ b/FFMpegCore/FFMpeg/FFMpegArgumentProcessor.cs @@ -65,7 +65,7 @@ void OnCancelEvent(object sender, EventArgs args) { errorCode = t.Result; cancellationTokenSource.Cancel(); - // _ffMpegArguments.Post(); + _ffMpegArguments.Post(); }), _ffMpegArguments.During(cancellationTokenSource.Token).ContinueWith(t => _ffMpegArguments.Post())); } catch (Exception e) @@ -111,7 +111,7 @@ await Task.WhenAll(instance.FinishedRunning().ContinueWith(t => { errorCode = t.Result; cancellationTokenSource.Cancel(); - // _ffMpegArguments.Post(); + _ffMpegArguments.Post(); }), _ffMpegArguments.During(cancellationTokenSource.Token).ContinueWith(t => _ffMpegArguments.Post())).ConfigureAwait(false); } catch (Exception e)