Merge branch 'feature/net7-windows-support-v5' of https://github.com/drasive/FFMpegCore into feature/net7-windows-support-v5

This commit is contained in:
Dimitri Vranken 2023-02-20 13:18:17 +01:00
commit 3ae6799ca2
9 changed files with 89 additions and 89 deletions

View file

@ -10,7 +10,7 @@ on:
- FFMpegCore.Test/** - FFMpegCore.Test/**
pull_request: pull_request:
branches: branches:
- master - main
- release - release
paths: paths:
- .github/workflows/ci.yml - .github/workflows/ci.yml

View file

@ -19,5 +19,5 @@ jobs:
run: dotnet pack FFMpegCore.sln --output build -c Release run: dotnet pack FFMpegCore.sln --output build -c Release
- name: Publish NuGet package - name: Publish NuGet package
run: dotnet nuget push build/*.nupkg --source nuget.org --api-key ${{ secrets.NUGET_TOKEN }} run: dotnet nuget push *.nupkg --skip-duplicate --source nuget.org --api-key ${{ secrets.NUGET_TOKEN }}

View file

@ -1,15 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<IsPackable>false</IsPackable> <IsPackable>false</IsPackable>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\FFMpegCore.Extensions.SkiaSharp\FFMpegCore.Extensions.SkiaSharp.csproj" /> <ProjectReference Include="..\FFMpegCore.Extensions.SkiaSharp\FFMpegCore.Extensions.SkiaSharp.csproj" />
<ProjectReference Include="..\FFMpegCore.Extensions.System.Drawing.Common\FFMpegCore.Extensions.System.Drawing.Common.csproj" /> <ProjectReference Include="..\FFMpegCore.Extensions.System.Drawing.Common\FFMpegCore.Extensions.System.Drawing.Common.csproj"/>
<ProjectReference Include="..\FFMpegCore\FFMpegCore.csproj" /> <ProjectReference Include="..\FFMpegCore\FFMpegCore.csproj"/>
</ItemGroup> </ItemGroup>
</Project> </Project>

View file

@ -1,21 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<IsPackable>true</IsPackable> <IsPackable>true</IsPackable>
<Description>Image extension for FFMpegCore using System.Common.Drawing</Description> <Description>Image extension for FFMpegCore using System.Common.Drawing</Description>
<PackageVersion>5.0.0</PackageVersion> <PackageVersion>5.0.0</PackageVersion>
<PackageReleaseNotes> <PackageOutputPath>../nupkg</PackageOutputPath>
</PackageReleaseNotes> <PackageReleaseNotes>
<PackageTags>ffmpeg ffprobe convert video audio mediafile resize analyze muxing</PackageTags> </PackageReleaseNotes>
<Authors>Malte Rosenbjerg, Vlad Jerca, Max Bagryantsev</Authors> <PackageTags>ffmpeg ffprobe convert video audio mediafile resize analyze muxing</PackageTags>
</PropertyGroup> <Authors>Malte Rosenbjerg, Vlad Jerca, Max Bagryantsev</Authors>
</PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="System.Drawing.Common" Version="7.0.0" /> <PackageReference Include="System.Drawing.Common" Version="7.0.0"/>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\FFMpegCore\FFMpegCore.csproj" /> <ProjectReference Include="..\FFMpegCore\FFMpegCore.csproj"/>
</ItemGroup> </ItemGroup>
</Project> </Project>

View file

@ -12,21 +12,21 @@
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> </PackageReference>
<PackageReference Include="FluentAssertions" Version="6.9.0" /> <PackageReference Include="FluentAssertions" Version="6.9.0"/>
<PackageReference Include="GitHubActionsTestLogger" Version="2.0.1"> <PackageReference Include="GitHubActionsTestLogger" Version="2.0.1">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> </PackageReference>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.4.1" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.4.1"/>
<PackageReference Include="MSTest.TestAdapter" Version="3.0.2" /> <PackageReference Include="MSTest.TestAdapter" Version="3.0.2"/>
<PackageReference Include="MSTest.TestFramework" Version="3.0.2" /> <PackageReference Include="MSTest.TestFramework" Version="3.0.2"/>
<PackageReference Include="SkiaSharp" Version="2.88.3" /> <PackageReference Include="SkiaSharp" Version="2.88.3" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\FFMpegCore.Extensions.SkiaSharp\FFMpegCore.Extensions.SkiaSharp.csproj" /> <ProjectReference Include="..\FFMpegCore.Extensions.SkiaSharp\FFMpegCore.Extensions.SkiaSharp.csproj" />
<ProjectReference Include="..\FFMpegCore.Extensions.System.Drawing.Common\FFMpegCore.Extensions.System.Drawing.Common.csproj" /> <ProjectReference Include="..\FFMpegCore.Extensions.System.Drawing.Common\FFMpegCore.Extensions.System.Drawing.Common.csproj"/>
<ProjectReference Include="..\FFMpegCore\FFMpegCore.csproj" /> <ProjectReference Include="..\FFMpegCore\FFMpegCore.csproj"/>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View file

@ -1,15 +1,5 @@
namespace FFMpegCore.Test.Resources namespace FFMpegCore.Test.Resources
{ {
public enum AudioType
{
Mp3
}
public enum ImageType
{
Png
}
public static class TestResources public static class TestResources
{ {
public static readonly string Mp4Video = "./Resources/input_3sec.mp4"; public static readonly string Mp4Video = "./Resources/input_3sec.mp4";

View file

@ -467,7 +467,7 @@ public void Video_Snapshot_InMemory_SkiaSharp()
[TestMethod, Timeout(BaseTimeoutMilliseconds)] [TestMethod, Timeout(BaseTimeoutMilliseconds)]
public void Video_Snapshot_PersistSnapshot() public void Video_Snapshot_PersistSnapshot()
{ {
var outputPath = new TemporaryFile("out.png"); using var outputPath = new TemporaryFile("out.png");
var input = FFProbe.Analyse(TestResources.Mp4Video); var input = FFProbe.Analyse(TestResources.Mp4Video);
FFMpeg.Snapshot(TestResources.Mp4Video, outputPath); FFMpeg.Snapshot(TestResources.Mp4Video, outputPath);
@ -481,10 +481,10 @@ public void Video_Snapshot_PersistSnapshot()
[TestMethod, Timeout(BaseTimeoutMilliseconds)] [TestMethod, Timeout(BaseTimeoutMilliseconds)]
public void Video_Join() public void Video_Join()
{ {
var inputCopy = new TemporaryFile("copy-input.mp4"); using var inputCopy = new TemporaryFile("copy-input.mp4");
File.Copy(TestResources.Mp4Video, inputCopy); 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 input = FFProbe.Analyse(TestResources.Mp4Video);
var success = FFMpeg.Join(outputPath, TestResources.Mp4Video, inputCopy); var success = FFMpeg.Join(outputPath, TestResources.Mp4Video, inputCopy);
Assert.IsTrue(success); Assert.IsTrue(success);
@ -515,7 +515,7 @@ public void Video_Join_Image_Sequence()
}); });
var imageAnalysis = FFProbe.Analyse(imageSet.First()); 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()); var success = FFMpeg.JoinImageSequence(outputFile, frameRate: 10, images: imageSet.ToArray());
Assert.IsTrue(success); Assert.IsTrue(success);
var result = FFProbe.Analyse(outputFile); var result = FFProbe.Analyse(outputFile);
@ -538,7 +538,7 @@ public void Video_With_Only_Audio_Should_Extract_Metadata()
public void Video_Duration() public void Video_Duration()
{ {
var video = FFProbe.Analyse(TestResources.Mp4Video); var video = FFProbe.Analyse(TestResources.Mp4Video);
var outputFile = new TemporaryFile("out.mp4"); using var outputFile = new TemporaryFile("out.mp4");
FFMpegArguments FFMpegArguments
.FromFileInput(TestResources.Mp4Video) .FromFileInput(TestResources.Mp4Video)
@ -557,7 +557,7 @@ public void Video_Duration()
[TestMethod, Timeout(BaseTimeoutMilliseconds)] [TestMethod, Timeout(BaseTimeoutMilliseconds)]
public void Video_UpdatesProgress() public void Video_UpdatesProgress()
{ {
var outputFile = new TemporaryFile("out.mp4"); using var outputFile = new TemporaryFile("out.mp4");
var percentageDone = 0.0; var percentageDone = 0.0;
var timeDone = TimeSpan.Zero; var timeDone = TimeSpan.Zero;
@ -598,7 +598,7 @@ void OnTimeProgess(TimeSpan time)
[TestMethod, Timeout(BaseTimeoutMilliseconds)] [TestMethod, Timeout(BaseTimeoutMilliseconds)]
public void Video_OutputsData() public void Video_OutputsData()
{ {
var outputFile = new TemporaryFile("out.mp4"); using var outputFile = new TemporaryFile("out.mp4");
var dataReceived = false; var dataReceived = false;
GlobalFFOptions.Configure(opt => opt.Encoding = Encoding.UTF8); GlobalFFOptions.Configure(opt => opt.Encoding = Encoding.UTF8);
@ -663,7 +663,7 @@ public void Video_TranscodeToMemory()
[TestMethod, Timeout(BaseTimeoutMilliseconds)] [TestMethod, Timeout(BaseTimeoutMilliseconds)]
public async Task Video_Cancel_Async() public async Task Video_Cancel_Async()
{ {
var outputFile = new TemporaryFile("out.mp4"); using var outputFile = new TemporaryFile("out.mp4");
var task = FFMpegArguments var task = FFMpegArguments
.FromFileInput("testsrc2=size=320x240[out0]; sine[out1]", false, args => args .FromFileInput("testsrc2=size=320x240[out0]; sine[out1]", false, args => args
@ -687,7 +687,7 @@ public async Task Video_Cancel_Async()
[TestMethod, Timeout(BaseTimeoutMilliseconds)] [TestMethod, Timeout(BaseTimeoutMilliseconds)]
public void Video_Cancel() public void Video_Cancel()
{ {
var outputFile = new TemporaryFile("out.mp4"); using var outputFile = new TemporaryFile("out.mp4");
var task = FFMpegArguments var task = FFMpegArguments
.FromFileInput("testsrc2=size=320x240[out0]; sine[out1]", false, args => args .FromFileInput("testsrc2=size=320x240[out0]; sine[out1]", false, args => args
.WithCustomArgument("-re") .WithCustomArgument("-re")
@ -708,7 +708,7 @@ public void Video_Cancel()
[TestMethod, Timeout(BaseTimeoutMilliseconds)] [TestMethod, Timeout(BaseTimeoutMilliseconds)]
public async Task Video_Cancel_Async_With_Timeout() public async Task Video_Cancel_Async_With_Timeout()
{ {
var outputFile = new TemporaryFile("out.mp4"); using var outputFile = new TemporaryFile("out.mp4");
var task = FFMpegArguments var task = FFMpegArguments
.FromFileInput("testsrc2=size=320x240[out0]; sine[out1]", false, args => args .FromFileInput("testsrc2=size=320x240[out0]; sine[out1]", false, args => args
@ -738,7 +738,7 @@ public async Task Video_Cancel_Async_With_Timeout()
[TestMethod, Timeout(BaseTimeoutMilliseconds)] [TestMethod, Timeout(BaseTimeoutMilliseconds)]
public async Task Video_Cancel_CancellationToken_Async() public async Task Video_Cancel_CancellationToken_Async()
{ {
var outputFile = new TemporaryFile("out.mp4"); using var outputFile = new TemporaryFile("out.mp4");
var cts = new CancellationTokenSource(); var cts = new CancellationTokenSource();
@ -763,7 +763,7 @@ public async Task Video_Cancel_CancellationToken_Async()
[TestMethod, Timeout(BaseTimeoutMilliseconds)] [TestMethod, Timeout(BaseTimeoutMilliseconds)]
public async Task Video_Cancel_CancellationToken_Async_Throws() 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(); var cts = new CancellationTokenSource();
@ -786,7 +786,7 @@ public async Task Video_Cancel_CancellationToken_Async_Throws()
[TestMethod, Timeout(BaseTimeoutMilliseconds)] [TestMethod, Timeout(BaseTimeoutMilliseconds)]
public void Video_Cancel_CancellationToken_Throws() public void Video_Cancel_CancellationToken_Throws()
{ {
var outputFile = new TemporaryFile("out.mp4"); using var outputFile = new TemporaryFile("out.mp4");
var cts = new CancellationTokenSource(); var cts = new CancellationTokenSource();
@ -808,7 +808,7 @@ public void Video_Cancel_CancellationToken_Throws()
[TestMethod, Timeout(BaseTimeoutMilliseconds)] [TestMethod, Timeout(BaseTimeoutMilliseconds)]
public async Task Video_Cancel_CancellationToken_Async_With_Timeout() 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(); var cts = new CancellationTokenSource();

View file

@ -66,25 +66,34 @@ public static async Task<bool> SnapshotAsync(string input, string output, Size?
/// <returns>Output video information.</returns> /// <returns>Output video information.</returns>
public static bool JoinImageSequence(string output, double frameRate = 30, params string[] images) public static bool JoinImageSequence(string output, double frameRate = 30, params string[] images)
{ {
int? width = null, height = null; var fileExtensions = images.Select(Path.GetExtension).Distinct().ToArray();
var tempFolderName = Path.Combine(GlobalFFOptions.Current.TemporaryFilesFolder, Guid.NewGuid().ToString()); if (fileExtensions.Length != 1)
var temporaryImageFiles = images.Select((imagePath, index) =>
{ {
var analysis = FFProbe.Analyse(imagePath); throw new ArgumentException("All images must have the same extension", nameof(images));
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')}{Path.GetExtension(imagePath)}"); var fileExtension = fileExtensions[0].ToLowerInvariant();
Directory.CreateDirectory(tempFolderName); int? width = null, height = null;
File.Copy(imagePath, destinationPath);
return destinationPath; var tempFolderName = Path.Combine(GlobalFFOptions.Current.TemporaryFilesFolder, Guid.NewGuid().ToString());
}).ToArray(); Directory.CreateDirectory(tempFolderName);
try 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 return FFMpegArguments
.FromFileInput(Path.Combine(tempFolderName, "%09d.png"), false) .FromFileInput(Path.Combine(tempFolderName, $"%09d{fileExtension}"), false)
.OutputToFile(output, true, options => options .OutputToFile(output, true, options => options
.ForcePixelFormat("yuv420p") .ForcePixelFormat("yuv420p")
.Resize(width!.Value, height!.Value) .Resize(width!.Value, height!.Value)
@ -93,8 +102,7 @@ public static bool JoinImageSequence(string output, double frameRate = 30, param
} }
finally finally
{ {
Cleanup(temporaryImageFiles); Directory.Delete(tempFolderName, true);
Directory.Delete(tempFolderName);
} }
} }

View file

@ -1,23 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<IsPackable>true</IsPackable> <IsPackable>true</IsPackable>
<Description>A .NET Standard FFMpeg/FFProbe wrapper for easily integrating media analysis and conversion into your .NET applications</Description> <Description>A .NET Standard FFMpeg/FFProbe wrapper for easily integrating media analysis and conversion into your .NET applications</Description>
<PackageVersion>5.0.0</PackageVersion> <PackageVersion>5.0.1</PackageVersion>
<PackageReleaseNotes> <PackageOutputPath>../nupkg</PackageOutputPath>
</PackageReleaseNotes> <PackageReleaseNotes>
<PackageTags>ffmpeg ffprobe convert video audio mediafile resize analyze muxing</PackageTags> </PackageReleaseNotes>
<Authors>Malte Rosenbjerg, Vlad Jerca, Max Bagryantsev</Authors> <PackageTags>ffmpeg ffprobe convert video audio mediafile resize analyze muxing</PackageTags>
<PackageReadmeFile>README.md</PackageReadmeFile> <Authors>Malte Rosenbjerg, Vlad Jerca, Max Bagryantsev</Authors>
</PropertyGroup> <PackageReadmeFile>README.md</PackageReadmeFile>
</PropertyGroup>
<ItemGroup> <ItemGroup>
<None Include="..\README.md" Pack="true" PackagePath="\" /> <None Include="..\README.md" Pack="true" PackagePath="\"/>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Instances" Version="3.0.0" /> <PackageReference Include="Instances" Version="3.0.0"/>
<PackageReference Include="System.Text.Json" Version="7.0.1" /> <PackageReference Include="System.Text.Json" Version="7.0.1"/>
</ItemGroup> </ItemGroup>
</Project> </Project>