mirror of
https://github.com/rosenbjerg/FFMpegCore.git
synced 2024-11-10 00:24:14 +01:00
Merge 49c2941474
into eb221c3e49
This commit is contained in:
commit
0f7c6454eb
4 changed files with 135 additions and 2 deletions
|
@ -9,6 +9,7 @@ namespace FFMpegCore.Test
|
||||||
public class ArgumentBuilderTest
|
public class ArgumentBuilderTest
|
||||||
{
|
{
|
||||||
private readonly string[] _concatFiles = { "1.mp4", "2.mp4", "3.mp4", "4.mp4" };
|
private readonly string[] _concatFiles = { "1.mp4", "2.mp4", "3.mp4", "4.mp4" };
|
||||||
|
private readonly string[] _multiFiles = { "1.mp3", "2.mp3", "3.mp3", "4.mp3" };
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public void Builder_BuildString_IO_1()
|
public void Builder_BuildString_IO_1()
|
||||||
|
@ -611,5 +612,86 @@ public void Builder_BuildString_TeeOutput()
|
||||||
-i "input.mp4" -f tee "[movflags=faststart]output.mp4|[f=mpegts:select=\'0:v:0\']http://server/path"
|
-i "input.mp4" -f tee "[movflags=faststart]output.mp4|[f=mpegts:select=\'0:v:0\']http://server/path"
|
||||||
""", str);
|
""", str);
|
||||||
}
|
}
|
||||||
|
[TestMethod]
|
||||||
|
public void Builder_BuildString_MultiInput()
|
||||||
|
{
|
||||||
|
var audioStreams = string.Join("", _multiFiles.Select((item, index) => $"[{index}:0]"));
|
||||||
|
var mixFilter = $"{audioStreams}amix=inputs={_multiFiles.Length}:duration=longest:dropout_transition=1:normalize=0[final]";
|
||||||
|
var ffmpegArgs = $"-filter_complex \"{mixFilter}\" -map \"[final]\"";
|
||||||
|
var str = FFMpegArguments
|
||||||
|
.FromFileInput(_multiFiles)
|
||||||
|
.OutputToFile("output.mp3", overwrite: true, options => options
|
||||||
|
.WithCustomArgument(ffmpegArgs)
|
||||||
|
.WithAudioCodec(AudioCodec.LibMp3Lame) // Set the audio codec to MP3
|
||||||
|
.WithAudioBitrate(128) // Set the bitrate to 128kbps
|
||||||
|
.WithAudioSamplingRate(48000) // Set the sample rate to 48kHz
|
||||||
|
.WithoutMetadata() // Remove metadata
|
||||||
|
.WithCustomArgument("-ac 2 -write_xing 0 -id3v2_version 0")) // Force 2 Channels
|
||||||
|
.Arguments;
|
||||||
|
Assert.AreEqual($"-i \"1.mp3\" -i \"2.mp3\" -i \"3.mp3\" -i \"4.mp3\" -filter_complex \"[0:0][1:0][2:0][3:0]amix=inputs=4:duration=longest:dropout_transition=1:normalize=0[final]\" -map \"[final]\" -c:a libmp3lame -b:a 128k -ar 48000 -map_metadata -1 -ac 2 -write_xing 0 -id3v2_version 0 \"output.mp3\" -y", str);
|
||||||
|
}
|
||||||
|
[TestMethod]
|
||||||
|
public void Pre_VerifyExists_AllFilesExist()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var filePaths = new List<string>
|
||||||
|
{
|
||||||
|
Path.GetTempFileName(),
|
||||||
|
Path.GetTempFileName(),
|
||||||
|
Path.GetTempFileName()
|
||||||
|
};
|
||||||
|
var argument = new MultiInputArgument(true, filePaths);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Act & Assert
|
||||||
|
argument.Pre(); // No exception should be thrown
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
// Cleanup
|
||||||
|
foreach (var filePath in filePaths)
|
||||||
|
{
|
||||||
|
File.Delete(filePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void Pre_VerifyExists_SomeFilesNotExist()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var filePaths = new List<string>
|
||||||
|
{
|
||||||
|
Path.GetTempFileName(),
|
||||||
|
"file2.mp4",
|
||||||
|
"file3.mp4"
|
||||||
|
};
|
||||||
|
var argument = new MultiInputArgument(true, filePaths);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Act & Assert
|
||||||
|
Assert.ThrowsException<FileNotFoundException>(() => argument.Pre());
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
// Cleanup
|
||||||
|
File.Delete(filePaths[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void Pre_VerifyExists_NoFilesExist()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var filePaths = new List<string>
|
||||||
|
{
|
||||||
|
"file1.mp4",
|
||||||
|
"file2.mp4",
|
||||||
|
"file3.mp4"
|
||||||
|
};
|
||||||
|
var argument = new MultiInputArgument(true, filePaths);
|
||||||
|
// Act & Assert
|
||||||
|
Assert.ThrowsException<FileNotFoundException>(() => argument.Pre());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
47
FFMpegCore/FFMpeg/Arguments/MultiInputArgument.cs
Normal file
47
FFMpegCore/FFMpeg/Arguments/MultiInputArgument.cs
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
namespace FFMpegCore.Arguments
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents input parameters for multiple files
|
||||||
|
/// </summary>
|
||||||
|
public class MultiInputArgument : IInputArgument
|
||||||
|
{
|
||||||
|
public readonly bool VerifyExists;
|
||||||
|
public readonly IEnumerable<string> FilePaths;
|
||||||
|
|
||||||
|
public MultiInputArgument(bool verifyExists, IEnumerable<string> filePaths)
|
||||||
|
{
|
||||||
|
VerifyExists = verifyExists;
|
||||||
|
FilePaths = filePaths;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MultiInputArgument(IEnumerable<string> filePaths, bool verifyExists) : this(verifyExists, filePaths) { }
|
||||||
|
|
||||||
|
public void Pre()
|
||||||
|
{
|
||||||
|
if (VerifyExists)
|
||||||
|
{
|
||||||
|
var missingFiles = new List<string>();
|
||||||
|
foreach (var filePath in FilePaths)
|
||||||
|
{
|
||||||
|
if (!File.Exists(filePath))
|
||||||
|
{
|
||||||
|
missingFiles.Add(filePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (missingFiles.Any())
|
||||||
|
{
|
||||||
|
throw new FileNotFoundException($"The following input files were not found: {string.Join(", ", missingFiles)}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task During(CancellationToken cancellationToken = default) => Task.CompletedTask;
|
||||||
|
public void Post() { }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Generates a combined input argument text for all file paths
|
||||||
|
/// </summary>
|
||||||
|
public string Text => string.Join(" ", FilePaths.Select(filePath => $"-i \"{filePath}\""));
|
||||||
|
}
|
||||||
|
}
|
|
@ -21,6 +21,7 @@ private string GetText()
|
||||||
public static FFMpegArguments FromConcatInput(IEnumerable<string> filePaths, Action<FFMpegArgumentOptions>? addArguments = null) => new FFMpegArguments().WithInput(new ConcatArgument(filePaths), addArguments);
|
public static FFMpegArguments FromConcatInput(IEnumerable<string> filePaths, Action<FFMpegArgumentOptions>? addArguments = null) => new FFMpegArguments().WithInput(new ConcatArgument(filePaths), addArguments);
|
||||||
public static FFMpegArguments FromDemuxConcatInput(IEnumerable<string> filePaths, Action<FFMpegArgumentOptions>? addArguments = null) => new FFMpegArguments().WithInput(new DemuxConcatArgument(filePaths), addArguments);
|
public static FFMpegArguments FromDemuxConcatInput(IEnumerable<string> filePaths, Action<FFMpegArgumentOptions>? addArguments = null) => new FFMpegArguments().WithInput(new DemuxConcatArgument(filePaths), addArguments);
|
||||||
public static FFMpegArguments FromFileInput(string filePath, bool verifyExists = true, Action<FFMpegArgumentOptions>? addArguments = null) => new FFMpegArguments().WithInput(new InputArgument(verifyExists, filePath), addArguments);
|
public static FFMpegArguments FromFileInput(string filePath, bool verifyExists = true, Action<FFMpegArgumentOptions>? addArguments = null) => new FFMpegArguments().WithInput(new InputArgument(verifyExists, filePath), addArguments);
|
||||||
|
public static FFMpegArguments FromFileInput(IEnumerable<string> filePath, bool verifyExists = true, Action<FFMpegArgumentOptions>? addArguments = null) => new FFMpegArguments().WithInput(new MultiInputArgument(verifyExists, filePath), addArguments);
|
||||||
public static FFMpegArguments FromFileInput(FileInfo fileInfo, Action<FFMpegArgumentOptions>? addArguments = null) => new FFMpegArguments().WithInput(new InputArgument(fileInfo.FullName, false), addArguments);
|
public static FFMpegArguments FromFileInput(FileInfo fileInfo, Action<FFMpegArgumentOptions>? addArguments = null) => new FFMpegArguments().WithInput(new InputArgument(fileInfo.FullName, false), addArguments);
|
||||||
public static FFMpegArguments FromUrlInput(Uri uri, Action<FFMpegArgumentOptions>? addArguments = null) => new FFMpegArguments().WithInput(new InputArgument(uri.AbsoluteUri, false), addArguments);
|
public static FFMpegArguments FromUrlInput(Uri uri, Action<FFMpegArgumentOptions>? addArguments = null) => new FFMpegArguments().WithInput(new InputArgument(uri.AbsoluteUri, false), addArguments);
|
||||||
public static FFMpegArguments FromDeviceInput(string device, Action<FFMpegArgumentOptions>? addArguments = null) => new FFMpegArguments().WithInput(new InputDeviceArgument(device), addArguments);
|
public static FFMpegArguments FromDeviceInput(string device, Action<FFMpegArgumentOptions>? addArguments = null) => new FFMpegArguments().WithInput(new InputDeviceArgument(device), addArguments);
|
||||||
|
@ -35,6 +36,7 @@ public FFMpegArguments WithGlobalOptions(Action<FFMpegGlobalArguments> configure
|
||||||
public FFMpegArguments AddConcatInput(IEnumerable<string> filePaths, Action<FFMpegArgumentOptions>? addArguments = null) => WithInput(new ConcatArgument(filePaths), addArguments);
|
public FFMpegArguments AddConcatInput(IEnumerable<string> filePaths, Action<FFMpegArgumentOptions>? addArguments = null) => WithInput(new ConcatArgument(filePaths), addArguments);
|
||||||
public FFMpegArguments AddDemuxConcatInput(IEnumerable<string> filePaths, Action<FFMpegArgumentOptions>? addArguments = null) => WithInput(new DemuxConcatArgument(filePaths), addArguments);
|
public FFMpegArguments AddDemuxConcatInput(IEnumerable<string> filePaths, Action<FFMpegArgumentOptions>? addArguments = null) => WithInput(new DemuxConcatArgument(filePaths), addArguments);
|
||||||
public FFMpegArguments AddFileInput(string filePath, bool verifyExists = true, Action<FFMpegArgumentOptions>? addArguments = null) => WithInput(new InputArgument(verifyExists, filePath), addArguments);
|
public FFMpegArguments AddFileInput(string filePath, bool verifyExists = true, Action<FFMpegArgumentOptions>? addArguments = null) => WithInput(new InputArgument(verifyExists, filePath), addArguments);
|
||||||
|
public FFMpegArguments AddFileInput(IEnumerable<string> filePath, bool verifyExists = true, Action<FFMpegArgumentOptions>? addArguments = null) => WithInput(new MultiInputArgument(verifyExists, filePath), addArguments);
|
||||||
public FFMpegArguments AddFileInput(FileInfo fileInfo, Action<FFMpegArgumentOptions>? addArguments = null) => WithInput(new InputArgument(fileInfo.FullName, false), addArguments);
|
public FFMpegArguments AddFileInput(FileInfo fileInfo, Action<FFMpegArgumentOptions>? addArguments = null) => WithInput(new InputArgument(fileInfo.FullName, false), addArguments);
|
||||||
public FFMpegArguments AddUrlInput(Uri uri, Action<FFMpegArgumentOptions>? addArguments = null) => WithInput(new InputArgument(uri.AbsoluteUri, false), addArguments);
|
public FFMpegArguments AddUrlInput(Uri uri, Action<FFMpegArgumentOptions>? addArguments = null) => WithInput(new InputArgument(uri.AbsoluteUri, false), addArguments);
|
||||||
public FFMpegArguments AddDeviceInput(string device, Action<FFMpegArgumentOptions>? addArguments = null) => WithInput(new InputDeviceArgument(device), addArguments);
|
public FFMpegArguments AddDeviceInput(string device, Action<FFMpegArgumentOptions>? addArguments = null) => WithInput(new InputDeviceArgument(device), addArguments);
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
<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.1.0</PackageVersion>
|
<PackageVersion>5.1.1</PackageVersion>
|
||||||
<PackageOutputPath>../nupkg</PackageOutputPath>
|
<PackageOutputPath>../nupkg</PackageOutputPath>
|
||||||
<PackageReleaseNotes>
|
<PackageReleaseNotes>
|
||||||
</PackageReleaseNotes>
|
</PackageReleaseNotes>
|
||||||
|
@ -18,7 +18,9 @@
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Instances" Version="3.0.0" />
|
<PackageReference Include="Instances" Version="3.0.0" />
|
||||||
<PackageReference Include="System.Text.Json" Version="7.0.3" />
|
<PackageReference Include="System.Text.Json" Version="8.0.4" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
Loading…
Reference in a new issue