mirror of
https://github.com/rosenbjerg/FFMpegCore.git
synced 2024-11-10 08:34:12 +01:00
Pan filter implementation and testing
This commit is contained in:
parent
78a703fc93
commit
7a661b6ab3
4 changed files with 138 additions and 3 deletions
|
@ -414,5 +414,38 @@ public void Builder_BuildString_ForcePixelFormat()
|
||||||
.OutputToFile("output.mp4", false, opt => opt.ForcePixelFormat("yuv444p")).Arguments;
|
.OutputToFile("output.mp4", false, opt => opt.ForcePixelFormat("yuv444p")).Arguments;
|
||||||
Assert.AreEqual("-i \"input.mp4\" -pix_fmt yuv444p \"output.mp4\"", str);
|
Assert.AreEqual("-i \"input.mp4\" -pix_fmt yuv444p \"output.mp4\"", str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void Builder_BuildString_PanAudioFilterChannelNumber()
|
||||||
|
{
|
||||||
|
var str = FFMpegArguments.FromFileInput("input.mp4")
|
||||||
|
.OutputToFile("output.mp4", false,
|
||||||
|
opt => opt.WithAudioFilters(filterOptions => filterOptions.Pan(2, "c0=c1", "c1=c1")))
|
||||||
|
.Arguments;
|
||||||
|
|
||||||
|
Assert.AreEqual("-i \"input.mp4\" -af \"pan=2c|c0=c1|c1=c1\" \"output.mp4\"", str);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void Builder_BuildString_PanAudioFilterChannelLayout()
|
||||||
|
{
|
||||||
|
var str = FFMpegArguments.FromFileInput("input.mp4")
|
||||||
|
.OutputToFile("output.mp4", false,
|
||||||
|
opt => opt.WithAudioFilters(filterOptions => filterOptions.Pan("stereo", "c0=c0", "c1=c1")))
|
||||||
|
.Arguments;
|
||||||
|
|
||||||
|
Assert.AreEqual("-i \"input.mp4\" -af \"pan=stereo|c0=c0|c1=c1\" \"output.mp4\"", str);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void Builder_BuildString_PanAudioFilterChannelNoOutputDefinition()
|
||||||
|
{
|
||||||
|
var str = FFMpegArguments.FromFileInput("input.mp4")
|
||||||
|
.OutputToFile("output.mp4", false,
|
||||||
|
opt => opt.WithAudioFilters(filterOptions => filterOptions.Pan("stereo")))
|
||||||
|
.Arguments;
|
||||||
|
|
||||||
|
Assert.AreEqual("-i \"input.mp4\" -af \"pan=stereo\" \"output.mp4\"", str);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -223,5 +223,63 @@ public void Audio_ToAAC_Args_Pipe_InvalidSampleRate()
|
||||||
.WithAudioCodec(AudioCodec.Aac))
|
.WithAudioCodec(AudioCodec.Aac))
|
||||||
.ProcessSynchronously());
|
.ProcessSynchronously());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[TestMethod, Timeout(10000)]
|
||||||
|
public void Audio_Pan_ToMono()
|
||||||
|
{
|
||||||
|
using var outputFile = new TemporaryFile($"out{VideoType.Mp4.Extension}");
|
||||||
|
|
||||||
|
var success = FFMpegArguments.FromFileInput(TestResources.Mp4Video)
|
||||||
|
.OutputToFile(outputFile, true,
|
||||||
|
argumentOptions => argumentOptions
|
||||||
|
.WithAudioFilters(filter => filter.Pan(1, "c0 < 0.9 * c0 + 0.1 * c1")))
|
||||||
|
.ProcessSynchronously();
|
||||||
|
|
||||||
|
var mediaAnalysis = FFProbe.Analyse(outputFile);
|
||||||
|
|
||||||
|
Assert.IsTrue(success);
|
||||||
|
Assert.AreEqual(1, mediaAnalysis.AudioStreams.Count);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod, Timeout(10000)]
|
||||||
|
public void Audio_Pan_ToMonoNoDefinitions()
|
||||||
|
{
|
||||||
|
using var outputFile = new TemporaryFile($"out{VideoType.Mp4.Extension}");
|
||||||
|
|
||||||
|
var success = FFMpegArguments.FromFileInput(TestResources.Mp4Video)
|
||||||
|
.OutputToFile(outputFile, true,
|
||||||
|
argumentOptions => argumentOptions
|
||||||
|
.WithAudioFilters(filter => filter.Pan(1)))
|
||||||
|
.ProcessSynchronously();
|
||||||
|
|
||||||
|
var mediaAnalysis = FFProbe.Analyse(outputFile);
|
||||||
|
|
||||||
|
Assert.IsTrue(success);
|
||||||
|
Assert.AreEqual(1, mediaAnalysis.AudioStreams.Count);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod, Timeout(10000)]
|
||||||
|
public void Audio_Pan_ToMonoChannelsToOutputDefinitionsMismatch()
|
||||||
|
{
|
||||||
|
using var outputFile = new TemporaryFile($"out{VideoType.Mp4.Extension}");
|
||||||
|
|
||||||
|
var ex = Assert.ThrowsException<ArgumentException>(() => FFMpegArguments.FromFileInput(TestResources.Mp4Video)
|
||||||
|
.OutputToFile(outputFile, true,
|
||||||
|
argumentOptions => argumentOptions
|
||||||
|
.WithAudioFilters(filter => filter.Pan(1, "c0=c0", "c1=c1")))
|
||||||
|
.ProcessSynchronously());
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod, Timeout(10000)]
|
||||||
|
public void Audio_Pan_ToMonoChannelsLayoutToOutputDefinitionsMismatch()
|
||||||
|
{
|
||||||
|
using var outputFile = new TemporaryFile($"out{VideoType.Mp4.Extension}");
|
||||||
|
|
||||||
|
var ex = Assert.ThrowsException<FFMpegException>(() => FFMpegArguments.FromFileInput(TestResources.Mp4Video)
|
||||||
|
.OutputToFile(outputFile, true,
|
||||||
|
argumentOptions => argumentOptions
|
||||||
|
.WithAudioFilters(filter => filter.Pan("mono", "c0=c0", "c1=c1")))
|
||||||
|
.ProcessSynchronously());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,7 +1,5 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Drawing;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using FFMpegCore.Enums;
|
|
||||||
using FFMpegCore.Exceptions;
|
using FFMpegCore.Exceptions;
|
||||||
|
|
||||||
namespace FFMpegCore.Arguments
|
namespace FFMpegCore.Arguments
|
||||||
|
@ -43,7 +41,10 @@ public interface IAudioFilterArgument
|
||||||
public class AudioFilterOptions
|
public class AudioFilterOptions
|
||||||
{
|
{
|
||||||
public List<IAudioFilterArgument> Arguments { get; } = new List<IAudioFilterArgument>();
|
public List<IAudioFilterArgument> Arguments { get; } = new List<IAudioFilterArgument>();
|
||||||
|
|
||||||
|
public AudioFilterOptions Pan(string channelLayout, params string[] outputDefinitions) => WithArgument(new PanArgument(channelLayout, outputDefinitions));
|
||||||
|
public AudioFilterOptions Pan(int channels, params string[] outputDefinitions) => WithArgument(new PanArgument(channels, outputDefinitions));
|
||||||
|
|
||||||
private AudioFilterOptions WithArgument(IAudioFilterArgument argument)
|
private AudioFilterOptions WithArgument(IAudioFilterArgument argument)
|
||||||
{
|
{
|
||||||
Arguments.Add(argument);
|
Arguments.Add(argument);
|
||||||
|
|
43
FFMpegCore/FFMpeg/Arguments/PanArgument.cs
Normal file
43
FFMpegCore/FFMpeg/Arguments/PanArgument.cs
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace FFMpegCore.Arguments
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents scale parameter
|
||||||
|
/// </summary>
|
||||||
|
public class PanArgument : IAudioFilterArgument
|
||||||
|
{
|
||||||
|
public readonly string ChannelLayout;
|
||||||
|
private readonly string[] _outputDefinitions;
|
||||||
|
|
||||||
|
public PanArgument(string channelLayout, params string[] outputDefinitions)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(channelLayout))
|
||||||
|
{
|
||||||
|
throw new ArgumentException("The channel layout must be set" ,nameof(channelLayout));
|
||||||
|
}
|
||||||
|
|
||||||
|
ChannelLayout = channelLayout;
|
||||||
|
|
||||||
|
_outputDefinitions = outputDefinitions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PanArgument(int channels, params string[] outputDefinitions)
|
||||||
|
{
|
||||||
|
if (channels <= 0) throw new ArgumentOutOfRangeException(nameof(channels));
|
||||||
|
|
||||||
|
if (outputDefinitions.Length > channels)
|
||||||
|
throw new ArgumentException("The number of output definitions must be equal or lower than number of channels", nameof(outputDefinitions));
|
||||||
|
|
||||||
|
ChannelLayout = $"{channels}c";
|
||||||
|
|
||||||
|
_outputDefinitions = outputDefinitions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Key { get; } = "pan";
|
||||||
|
|
||||||
|
public string Value =>
|
||||||
|
string.Join("|", Enumerable.Empty<string>().Append(ChannelLayout).Concat(_outputDefinitions));
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue