From ad5dca3cd64944467cd69a186a2c79e390334f3e Mon Sep 17 00:00:00 2001 From: Malte Rosenbjerg Date: Thu, 16 Feb 2023 23:55:10 +0100 Subject: [PATCH 1/9] Ensure all images have same file extension and handle that --- FFMpegCore/FFMpeg/FFMpeg.cs | 38 ++++++++++++++++++++++-------------- FFMpegCore/FFMpegCore.csproj | 2 +- 2 files changed, 24 insertions(+), 16 deletions(-) diff --git a/FFMpegCore/FFMpeg/FFMpeg.cs b/FFMpegCore/FFMpeg/FFMpeg.cs index 58526b8..94f35c0 100644 --- a/FFMpegCore/FFMpeg/FFMpeg.cs +++ b/FFMpegCore/FFMpeg/FFMpeg.cs @@ -66,25 +66,34 @@ public static async Task SnapshotAsync(string input, string output, Size? /// Output video information. public static bool JoinImageSequence(string output, double frameRate = 30, params string[] images) { - int? width = null, height = null; - var tempFolderName = Path.Combine(GlobalFFOptions.Current.TemporaryFilesFolder, Guid.NewGuid().ToString()); - var temporaryImageFiles = images.Select((imagePath, index) => + var fileExtensions = images.Select(Path.GetExtension).Distinct().ToArray(); + if (fileExtensions.Length != 1) { - var analysis = FFProbe.Analyse(imagePath); - FFMpegHelper.ConversionSizeExceptionCheck(analysis.PrimaryVideoStream!.Width, analysis.PrimaryVideoStream!.Height); - width ??= analysis.PrimaryVideoStream.Width; - height ??= analysis.PrimaryVideoStream.Height; + throw new ArgumentException("All images must have the same extension", nameof(images)); + } - var destinationPath = Path.Combine(tempFolderName, $"{index.ToString().PadLeft(9, '0')}{Path.GetExtension(imagePath)}"); - Directory.CreateDirectory(tempFolderName); - File.Copy(imagePath, destinationPath); - return destinationPath; - }).ToArray(); + var fileExtension = fileExtensions[0].ToLowerInvariant(); + int? width = null, height = null; + + var tempFolderName = Path.Combine(GlobalFFOptions.Current.TemporaryFilesFolder, Guid.NewGuid().ToString()); + Directory.CreateDirectory(tempFolderName); try { + var index = 0; + foreach (var imagePath in images) + { + var analysis = FFProbe.Analyse(imagePath); + FFMpegHelper.ConversionSizeExceptionCheck(analysis.PrimaryVideoStream!.Width, analysis.PrimaryVideoStream!.Height); + width ??= analysis.PrimaryVideoStream.Width; + height ??= analysis.PrimaryVideoStream.Height; + + var destinationPath = Path.Combine(tempFolderName, $"{index++.ToString().PadLeft(9, '0')}{fileExtension}"); + File.Copy(imagePath, destinationPath); + } + return FFMpegArguments - .FromFileInput(Path.Combine(tempFolderName, "%09d.png"), false) + .FromFileInput(Path.Combine(tempFolderName, $"%09d{fileExtension}"), false) .OutputToFile(output, true, options => options .ForcePixelFormat("yuv420p") .Resize(width!.Value, height!.Value) @@ -93,8 +102,7 @@ public static bool JoinImageSequence(string output, double frameRate = 30, param } finally { - Cleanup(temporaryImageFiles); - Directory.Delete(tempFolderName); + Directory.Delete(tempFolderName, true); } } diff --git a/FFMpegCore/FFMpegCore.csproj b/FFMpegCore/FFMpegCore.csproj index 7c3f7bb..5db9cc8 100644 --- a/FFMpegCore/FFMpegCore.csproj +++ b/FFMpegCore/FFMpegCore.csproj @@ -3,7 +3,7 @@ true A .NET Standard FFMpeg/FFProbe wrapper for easily integrating media analysis and conversion into your .NET applications - 5.0.0 + 5.0.1 ffmpeg ffprobe convert video audio mediafile resize analyze muxing From 02d2b4261b0f5519c0c0137b9f0b2f44c89113d2 Mon Sep 17 00:00:00 2001 From: Malte Rosenbjerg Date: Thu, 16 Feb 2023 23:55:20 +0100 Subject: [PATCH 2/9] Add missing usings on tests --- FFMpegCore.Test/VideoTest.cs | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/FFMpegCore.Test/VideoTest.cs b/FFMpegCore.Test/VideoTest.cs index e3e4b6b..fec8386 100644 --- a/FFMpegCore.Test/VideoTest.cs +++ b/FFMpegCore.Test/VideoTest.cs @@ -413,7 +413,7 @@ public void Video_Snapshot_InMemory() [TestMethod, Timeout(10000)] public void Video_Snapshot_PersistSnapshot() { - var outputPath = new TemporaryFile("out.png"); + using var outputPath = new TemporaryFile("out.png"); var input = FFProbe.Analyse(TestResources.Mp4Video); FFMpeg.Snapshot(TestResources.Mp4Video, outputPath); @@ -427,10 +427,10 @@ public void Video_Snapshot_PersistSnapshot() [TestMethod, Timeout(10000)] public void Video_Join() { - var inputCopy = new TemporaryFile("copy-input.mp4"); + using var inputCopy = new TemporaryFile("copy-input.mp4"); File.Copy(TestResources.Mp4Video, inputCopy); - var outputPath = new TemporaryFile("out.mp4"); + using var outputPath = new TemporaryFile("out.mp4"); var input = FFProbe.Analyse(TestResources.Mp4Video); var success = FFMpeg.Join(outputPath, TestResources.Mp4Video, inputCopy); Assert.IsTrue(success); @@ -461,7 +461,7 @@ public void Video_Join_Image_Sequence() }); var imageAnalysis = FFProbe.Analyse(imageSet.First()); - var outputFile = new TemporaryFile("out.mp4"); + using var outputFile = new TemporaryFile("out.mp4"); var success = FFMpeg.JoinImageSequence(outputFile, frameRate: 10, images: imageSet.ToArray()); Assert.IsTrue(success); var result = FFProbe.Analyse(outputFile); @@ -484,7 +484,7 @@ public void Video_With_Only_Audio_Should_Extract_Metadata() public void Video_Duration() { var video = FFProbe.Analyse(TestResources.Mp4Video); - var outputFile = new TemporaryFile("out.mp4"); + using var outputFile = new TemporaryFile("out.mp4"); FFMpegArguments .FromFileInput(TestResources.Mp4Video) @@ -503,7 +503,7 @@ public void Video_Duration() [TestMethod, Timeout(10000)] public void Video_UpdatesProgress() { - var outputFile = new TemporaryFile("out.mp4"); + using var outputFile = new TemporaryFile("out.mp4"); var percentageDone = 0.0; var timeDone = TimeSpan.Zero; @@ -544,7 +544,7 @@ void OnTimeProgess(TimeSpan time) [TestMethod, Timeout(10000)] public void Video_OutputsData() { - var outputFile = new TemporaryFile("out.mp4"); + using var outputFile = new TemporaryFile("out.mp4"); var dataReceived = false; GlobalFFOptions.Configure(opt => opt.Encoding = Encoding.UTF8); @@ -604,7 +604,7 @@ public void Video_TranscodeToMemory() [TestMethod, Timeout(10000)] public async Task Video_Cancel_Async() { - var outputFile = new TemporaryFile("out.mp4"); + using var outputFile = new TemporaryFile("out.mp4"); var task = FFMpegArguments .FromFileInput("testsrc2=size=320x240[out0]; sine[out1]", false, args => args @@ -628,7 +628,7 @@ public async Task Video_Cancel_Async() [TestMethod, Timeout(10000)] public void Video_Cancel() { - var outputFile = new TemporaryFile("out.mp4"); + using var outputFile = new TemporaryFile("out.mp4"); var task = FFMpegArguments .FromFileInput("testsrc2=size=320x240[out0]; sine[out1]", false, args => args .WithCustomArgument("-re") @@ -649,7 +649,7 @@ public void Video_Cancel() [TestMethod, Timeout(10000)] public async Task Video_Cancel_Async_With_Timeout() { - var outputFile = new TemporaryFile("out.mp4"); + using var outputFile = new TemporaryFile("out.mp4"); var task = FFMpegArguments .FromFileInput("testsrc2=size=320x240[out0]; sine[out1]", false, args => args @@ -679,7 +679,7 @@ public async Task Video_Cancel_Async_With_Timeout() [TestMethod, Timeout(10000)] public async Task Video_Cancel_CancellationToken_Async() { - var outputFile = new TemporaryFile("out.mp4"); + using var outputFile = new TemporaryFile("out.mp4"); var cts = new CancellationTokenSource(); @@ -704,7 +704,7 @@ public async Task Video_Cancel_CancellationToken_Async() [TestMethod, Timeout(10000)] public async Task Video_Cancel_CancellationToken_Async_Throws() { - var outputFile = new TemporaryFile("out.mp4"); + using var outputFile = new TemporaryFile("out.mp4"); var cts = new CancellationTokenSource(); @@ -727,7 +727,7 @@ public async Task Video_Cancel_CancellationToken_Async_Throws() [TestMethod, Timeout(10000)] public void Video_Cancel_CancellationToken_Throws() { - var outputFile = new TemporaryFile("out.mp4"); + using var outputFile = new TemporaryFile("out.mp4"); var cts = new CancellationTokenSource(); @@ -749,7 +749,7 @@ public void Video_Cancel_CancellationToken_Throws() [TestMethod, Timeout(10000)] public async Task Video_Cancel_CancellationToken_Async_With_Timeout() { - var outputFile = new TemporaryFile("out.mp4"); + using var outputFile = new TemporaryFile("out.mp4"); var cts = new CancellationTokenSource(); From 8b69ed104aef42203f96dc72bfc87b4c12b00424 Mon Sep 17 00:00:00 2001 From: Malte Rosenbjerg Date: Thu, 16 Feb 2023 23:55:28 +0100 Subject: [PATCH 3/9] Remove unused enums --- FFMpegCore.Test/Resources/TestResources.cs | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/FFMpegCore.Test/Resources/TestResources.cs b/FFMpegCore.Test/Resources/TestResources.cs index de84080..b958b80 100644 --- a/FFMpegCore.Test/Resources/TestResources.cs +++ b/FFMpegCore.Test/Resources/TestResources.cs @@ -1,15 +1,5 @@ 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"; From d6517fa1ef54517069e7f817ccbe1b8e7cf314fd Mon Sep 17 00:00:00 2001 From: Malte Rosenbjerg Date: Thu, 16 Feb 2023 23:58:20 +0100 Subject: [PATCH 4/9] Fix CI trigger after rename --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c6d3529..d00c29b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,7 +10,7 @@ on: - FFMpegCore.Test/** pull_request: branches: - - master + - main - release paths: - .github/workflows/ci.yml From 5b34d04a3585ef2e08a3d37aaf77a4f23184a909 Mon Sep 17 00:00:00 2001 From: Malte Rosenbjerg Date: Fri, 17 Feb 2023 00:12:32 +0100 Subject: [PATCH 5/9] Add PackageOutputPath and format --- .github/workflows/release.yml | 2 +- ...re.Extensions.System.Drawing.Common.csproj | 31 ++++++++-------- FFMpegCore/FFMpegCore.csproj | 35 ++++++++++--------- 3 files changed, 35 insertions(+), 33 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 0c7725b..03504f0 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -19,5 +19,5 @@ jobs: run: dotnet pack FFMpegCore.sln --output build -c Release - name: Publish NuGet package - run: dotnet nuget push build/*.nupkg --source nuget.org --api-key ${{ secrets.NUGET_TOKEN }} + run: dotnet nuget push *.nupkg --source nuget.org --api-key ${{ secrets.NUGET_TOKEN }} diff --git a/FFMpegCore.Extensions.System.Drawing.Common/FFMpegCore.Extensions.System.Drawing.Common.csproj b/FFMpegCore.Extensions.System.Drawing.Common/FFMpegCore.Extensions.System.Drawing.Common.csproj index aafb577..13cdc1a 100644 --- a/FFMpegCore.Extensions.System.Drawing.Common/FFMpegCore.Extensions.System.Drawing.Common.csproj +++ b/FFMpegCore.Extensions.System.Drawing.Common/FFMpegCore.Extensions.System.Drawing.Common.csproj @@ -1,21 +1,22 @@ - - true - Image extension for FFMpegCore using System.Common.Drawing - 5.0.0 - - - ffmpeg ffprobe convert video audio mediafile resize analyze muxing - Malte Rosenbjerg, Vlad Jerca, Max Bagryantsev - + + true + Image extension for FFMpegCore using System.Common.Drawing + 5.0.0 + ../nupkg + + + ffmpeg ffprobe convert video audio mediafile resize analyze muxing + Malte Rosenbjerg, Vlad Jerca, Max Bagryantsev + - - - + + + - - - + + + diff --git a/FFMpegCore/FFMpegCore.csproj b/FFMpegCore/FFMpegCore.csproj index 5db9cc8..843bdba 100644 --- a/FFMpegCore/FFMpegCore.csproj +++ b/FFMpegCore/FFMpegCore.csproj @@ -1,23 +1,24 @@  - - true - A .NET Standard FFMpeg/FFProbe wrapper for easily integrating media analysis and conversion into your .NET applications - 5.0.1 - - - ffmpeg ffprobe convert video audio mediafile resize analyze muxing - Malte Rosenbjerg, Vlad Jerca, Max Bagryantsev - README.md - + + true + A .NET Standard FFMpeg/FFProbe wrapper for easily integrating media analysis and conversion into your .NET applications + 5.0.1 + ../nupkg + + + ffmpeg ffprobe convert video audio mediafile resize analyze muxing + Malte Rosenbjerg, Vlad Jerca, Max Bagryantsev + README.md + - - - + + + - - - - + + + + From daa512c294f3ec2021b6d30c5f8a0cae9cc793aa Mon Sep 17 00:00:00 2001 From: Malte Rosenbjerg Date: Fri, 17 Feb 2023 00:13:34 +0100 Subject: [PATCH 6/9] Format remaining csproj files --- FFMpegCore.Examples/FFMpegCore.Examples.csproj | 18 +++++++++--------- FFMpegCore.Test/FFMpegCore.Test.csproj | 12 ++++++------ 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/FFMpegCore.Examples/FFMpegCore.Examples.csproj b/FFMpegCore.Examples/FFMpegCore.Examples.csproj index db3c66e..555f4b7 100644 --- a/FFMpegCore.Examples/FFMpegCore.Examples.csproj +++ b/FFMpegCore.Examples/FFMpegCore.Examples.csproj @@ -1,14 +1,14 @@ - - Exe - net6.0 - false - + + Exe + net6.0 + false + - - - - + + + + diff --git a/FFMpegCore.Test/FFMpegCore.Test.csproj b/FFMpegCore.Test/FFMpegCore.Test.csproj index def07d2..0243372 100644 --- a/FFMpegCore.Test/FFMpegCore.Test.csproj +++ b/FFMpegCore.Test/FFMpegCore.Test.csproj @@ -12,19 +12,19 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive - - - + + + - - + + From 8fff02d8d6ab09c5045fa4f2c75466804720a44e Mon Sep 17 00:00:00 2001 From: Malte Rosenbjerg Date: Fri, 17 Feb 2023 00:14:23 +0100 Subject: [PATCH 7/9] Add --skip-duplicate --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 03504f0..9ec3258 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -19,5 +19,5 @@ jobs: run: dotnet pack FFMpegCore.sln --output build -c Release - name: Publish NuGet package - run: dotnet nuget push *.nupkg --source nuget.org --api-key ${{ secrets.NUGET_TOKEN }} + run: dotnet nuget push *.nupkg --skip-duplicate --source nuget.org --api-key ${{ secrets.NUGET_TOKEN }} From 2e9f5f117090f410682957cb945e7bed787b40e3 Mon Sep 17 00:00:00 2001 From: Malte Rosenbjerg Date: Fri, 17 Feb 2023 00:23:17 +0100 Subject: [PATCH 8/9] Remove --output build --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 0c7725b..5356f8d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -16,7 +16,7 @@ jobs: dotnet-version: '7.0.x' - name: Build solution - run: dotnet pack FFMpegCore.sln --output build -c Release + run: dotnet pack FFMpegCore.sln -c Release - name: Publish NuGet package run: dotnet nuget push build/*.nupkg --source nuget.org --api-key ${{ secrets.NUGET_TOKEN }} From 55c90fb081820dd01f81ddabe18cda69275a60a2 Mon Sep 17 00:00:00 2001 From: Malte Rosenbjerg Date: Fri, 17 Feb 2023 00:27:12 +0100 Subject: [PATCH 9/9] Fix nupkg directory --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 676cfd2..00a1ea7 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -19,5 +19,5 @@ jobs: run: dotnet pack FFMpegCore.sln -c Release - name: Publish NuGet package - run: dotnet nuget push *.nupkg --skip-duplicate --source nuget.org --api-key ${{ secrets.NUGET_TOKEN }} + run: dotnet nuget push nupkg/*.nupkg --skip-duplicate --source nuget.org --api-key ${{ secrets.NUGET_TOKEN }}