FFMpegCore: use the argument builder in the ffmpeg methods

Former-commit-id: 3729d65e24
This commit is contained in:
Vlad Jerca 2019-02-08 18:17:05 +02:00
parent 9b855736ab
commit b0c2a7ea92
10 changed files with 158 additions and 192 deletions

View file

@ -25,13 +25,12 @@ public ArgumentBuilderTests() : base()
private string GetArgumentsString(params Argument[] args) private string GetArgumentsString(params Argument[] args)
{ {
var container = new ArgumentsContainer(); var container = new ArgumentsContainer();
container.Add(new OutputArgument("output.mp4"));
container.Add(new InputArgument("input.mp4")); container.Add(new InputArgument("input.mp4"));
foreach (var a in args) foreach (var a in args)
{ {
container.Add(a); container.Add(a);
} }
container.Add(new OutputArgument("output.mp4"));
return builder.BuildArguments(container); return builder.BuildArguments(container);
} }
@ -42,7 +41,7 @@ public void Builder_BuildString_IO_1()
{ {
var str = GetArgumentsString(); var str = GetArgumentsString();
Assert.IsTrue(str == "-i \"input.mp4\" \"output.mp4\""); Assert.AreEqual(str, "-i \"input.mp4\" \"output.mp4\"");
} }
[TestMethod] [TestMethod]
@ -50,15 +49,14 @@ public void Builder_BuildString_Scale()
{ {
var str = GetArgumentsString(new ScaleArgument(VideoSize.Hd)); var str = GetArgumentsString(new ScaleArgument(VideoSize.Hd));
Assert.IsTrue(str == "-i \"input.mp4\" -vf scale=-1:720 \"output.mp4\""); Assert.AreEqual(str, "-i \"input.mp4\" -vf scale=-1:720 \"output.mp4\"");
} }
[TestMethod] [TestMethod]
public void Builder_BuildString_AudioCodec() public void Builder_BuildString_AudioCodec()
{ {
var str = GetArgumentsString(new AudioCodecArgument(AudioCodec.Aac, AudioQuality.Normal)); var str = GetArgumentsString(new AudioCodecArgument(AudioCodec.Aac, AudioQuality.Normal));
Assert.AreEqual(str, "-i \"input.mp4\" -codec:a aac -b:a 128k -strict experimental \"output.mp4\"");
Assert.IsTrue(str == "-i \"input.mp4\" -codec:a aac -b:a 128k -strict experimental \"output.mp4\"");
} }
[TestMethod] [TestMethod]
@ -66,20 +64,20 @@ public void Builder_BuildString_BitStream()
{ {
var str = GetArgumentsString(new BitStreamFilterArgument(Channel.Audio, Filter.H264_Mp4ToAnnexB)); var str = GetArgumentsString(new BitStreamFilterArgument(Channel.Audio, Filter.H264_Mp4ToAnnexB));
Assert.IsTrue(str == "-i \"input.mp4\" -bsf:a h264_mp4toannexb \"output.mp4\""); Assert.AreEqual(str, "-i \"input.mp4\" -bsf:a h264_mp4toannexb \"output.mp4\"");
} }
[TestMethod] [TestMethod]
public void Builder_BuildString_Concat() public void Builder_BuildString_Concat()
{ {
var container = new ArgumentsContainer(); var container = new ArgumentsContainer();
container.Add(new OutputArgument("output.mp4"));
container.Add(new ConcatArgument(concatFiles)); container.Add(new ConcatArgument(concatFiles));
container.Add(new OutputArgument("output.mp4"));
var str = builder.BuildArguments(container); var str = builder.BuildArguments(container);
Assert.IsTrue(str == "-i \"concat:1.mp4|2.mp4|3.mp4|4.mp4\" \"output.mp4\""); Assert.AreEqual(str, "-i \"concat:1.mp4|2.mp4|3.mp4|4.mp4\" \"output.mp4\"");
} }
[TestMethod] [TestMethod]
@ -87,7 +85,7 @@ public void Builder_BuildString_Copy_Audio()
{ {
var str = GetArgumentsString(new CopyArgument(Channel.Audio)); var str = GetArgumentsString(new CopyArgument(Channel.Audio));
Assert.IsTrue(str == "-i \"input.mp4\" -c:a copy \"output.mp4\""); Assert.AreEqual(str, "-i \"input.mp4\" -c:a copy \"output.mp4\"");
} }
@ -96,7 +94,7 @@ public void Builder_BuildString_Copy_Video()
{ {
var str = GetArgumentsString(new CopyArgument(Channel.Video)); var str = GetArgumentsString(new CopyArgument(Channel.Video));
Assert.IsTrue(str == "-i \"input.mp4\" -c:v copy \"output.mp4\""); Assert.AreEqual(str, "-i \"input.mp4\" -c:v copy \"output.mp4\"");
} }
[TestMethod] [TestMethod]
@ -104,7 +102,7 @@ public void Builder_BuildString_Copy_Both()
{ {
var str = GetArgumentsString(new CopyArgument(Channel.Both)); var str = GetArgumentsString(new CopyArgument(Channel.Both));
Assert.IsTrue(str == "-i \"input.mp4\" -c copy \"output.mp4\""); Assert.AreEqual(str, "-i \"input.mp4\" -c copy \"output.mp4\"");
} }
[TestMethod] [TestMethod]
@ -112,7 +110,7 @@ public void Builder_BuildString_CpuSpeed()
{ {
var str = GetArgumentsString(new CpuSpeedArgument(10)); var str = GetArgumentsString(new CpuSpeedArgument(10));
Assert.IsTrue(str == "-i \"input.mp4\" -quality good -cpu-used 10 -deadline realtime \"output.mp4\""); Assert.AreEqual(str, "-i \"input.mp4\" -quality good -cpu-used 10 -deadline realtime \"output.mp4\"");
} }
[TestMethod] [TestMethod]
@ -120,7 +118,7 @@ public void Builder_BuildString_ForceFormat()
{ {
var str = GetArgumentsString(new ForceFormatArgument(VideoCodec.LibX264)); var str = GetArgumentsString(new ForceFormatArgument(VideoCodec.LibX264));
Assert.IsTrue(str == "-i \"input.mp4\" -f libx264 \"output.mp4\""); Assert.AreEqual(str, "-i \"input.mp4\" -f libx264 \"output.mp4\"");
} }
[TestMethod] [TestMethod]
@ -128,7 +126,7 @@ public void Builder_BuildString_FrameOutputCount()
{ {
var str = GetArgumentsString(new FrameOutputCountArgument(50)); var str = GetArgumentsString(new FrameOutputCountArgument(50));
Assert.IsTrue(str == "-i \"input.mp4\" -vframes 50 \"output.mp4\""); Assert.AreEqual(str, "-i \"input.mp4\" -vframes 50 \"output.mp4\"");
} }
[TestMethod] [TestMethod]
@ -136,7 +134,7 @@ public void Builder_BuildString_FrameRate()
{ {
var str = GetArgumentsString(new FrameRateArgument(50)); var str = GetArgumentsString(new FrameRateArgument(50));
Assert.IsTrue(str == "-i \"input.mp4\" -r 50 \"output.mp4\""); Assert.AreEqual(str, "-i \"input.mp4\" -r 50 \"output.mp4\"");
} }
[TestMethod] [TestMethod]
@ -144,7 +142,7 @@ public void Builder_BuildString_Loop()
{ {
var str = GetArgumentsString(new LoopArgument(50)); var str = GetArgumentsString(new LoopArgument(50));
Assert.IsTrue(str == "-i \"input.mp4\" -loop 50 \"output.mp4\""); Assert.AreEqual(str, "-i \"input.mp4\" -loop 50 \"output.mp4\"");
} }
[TestMethod] [TestMethod]
@ -152,7 +150,7 @@ public void Builder_BuildString_Seek()
{ {
var str = GetArgumentsString(new SeekArgument(TimeSpan.FromSeconds(10))); var str = GetArgumentsString(new SeekArgument(TimeSpan.FromSeconds(10)));
Assert.IsTrue(str == "-i \"input.mp4\" -ss 00:00:10 \"output.mp4\""); Assert.AreEqual(str, "-i \"input.mp4\" -ss 00:00:10 \"output.mp4\"");
} }
[TestMethod] [TestMethod]
@ -160,7 +158,7 @@ public void Builder_BuildString_Shortest()
{ {
var str = GetArgumentsString(new ShortestArgument(true)); var str = GetArgumentsString(new ShortestArgument(true));
Assert.IsTrue(str == "-i \"input.mp4\" -shortest \"output.mp4\""); Assert.AreEqual(str, "-i \"input.mp4\" -shortest \"output.mp4\"");
} }
[TestMethod] [TestMethod]
@ -168,7 +166,7 @@ public void Builder_BuildString_Size()
{ {
var str = GetArgumentsString(new SizeArgument(1920, 1080)); var str = GetArgumentsString(new SizeArgument(1920, 1080));
Assert.IsTrue(str == "-i \"input.mp4\" -s 1920x1080 \"output.mp4\""); Assert.AreEqual(str, "-i \"input.mp4\" -s 1920x1080 \"output.mp4\"");
} }
[TestMethod] [TestMethod]
@ -176,7 +174,7 @@ public void Builder_BuildString_Speed()
{ {
var str = GetArgumentsString(new SpeedArgument(Speed.Fast)); var str = GetArgumentsString(new SpeedArgument(Speed.Fast));
Assert.IsTrue(str == "-i \"input.mp4\" -preset fast \"output.mp4\""); Assert.AreEqual(str, "-i \"input.mp4\" -preset fast \"output.mp4\"");
} }
[TestMethod] [TestMethod]
@ -184,7 +182,7 @@ public void Builder_BuildString_StartNumber()
{ {
var str = GetArgumentsString(new StartNumberArgument(50)); var str = GetArgumentsString(new StartNumberArgument(50));
Assert.IsTrue(str == "-i \"input.mp4\" -start_number 50 \"output.mp4\""); Assert.AreEqual(str, "-i \"input.mp4\" -start_number 50 \"output.mp4\"");
} }
[TestMethod] [TestMethod]
@ -192,7 +190,7 @@ public void Builder_BuildString_Threads_1()
{ {
var str = GetArgumentsString(new ThreadsArgument(50)); var str = GetArgumentsString(new ThreadsArgument(50));
Assert.IsTrue(str == "-i \"input.mp4\" -threads 50 \"output.mp4\""); Assert.AreEqual(str, "-i \"input.mp4\" -threads 50 \"output.mp4\"");
} }
[TestMethod] [TestMethod]
@ -200,7 +198,7 @@ public void Builder_BuildString_Threads_2()
{ {
var str = GetArgumentsString(new ThreadsArgument(true)); var str = GetArgumentsString(new ThreadsArgument(true));
Assert.IsTrue(str == $"-i \"input.mp4\" -threads {Environment.ProcessorCount} \"output.mp4\""); Assert.AreEqual(str, $"-i \"input.mp4\" -threads {Environment.ProcessorCount} \"output.mp4\"");
} }
@ -209,7 +207,7 @@ public void Builder_BuildString_Codec()
{ {
var str = GetArgumentsString(new VideoCodecArgument(VideoCodec.LibX264)); var str = GetArgumentsString(new VideoCodecArgument(VideoCodec.LibX264));
Assert.IsTrue(str == "-i \"input.mp4\" -codec:v libx264 -pix_fmt yuv420p \"output.mp4\""); Assert.AreEqual(str, "-i \"input.mp4\" -codec:v libx264 -pix_fmt yuv420p \"output.mp4\"");
} }
[TestMethod] [TestMethod]
@ -217,7 +215,7 @@ public void Builder_BuildString_Codec_Override()
{ {
var str = GetArgumentsString(new VideoCodecArgument(VideoCodec.LibX264), new OverrideArgument()); var str = GetArgumentsString(new VideoCodecArgument(VideoCodec.LibX264), new OverrideArgument());
Assert.IsTrue(str == "-i \"input.mp4\" -codec:v libx264 -pix_fmt yuv420p \"output.mp4\" -y"); Assert.AreEqual(str, "-i \"input.mp4\" -codec:v libx264 -pix_fmt yuv420p -y \"output.mp4\"");
} }
} }
} }

View file

@ -69,11 +69,17 @@ public void Convert(VideoType type, ArgumentsContainer container)
{ {
var input = VideoInfo.FromFileInfo(Input); var input = VideoInfo.FromFileInfo(Input);
container.Add(new InputArgument(input)); var arguments = new ArgumentsContainer();
container.Add(new OutputArgument(output)); arguments.Add(new InputArgument(input));
foreach (var arg in container)
{
arguments.Add(arg.Value);
}
arguments.Add(new OutputArgument(output));
var scaling = container.Find<ScaleArgument>(); var scaling = container.Find<ScaleArgument>();
Encoder.Convert(container); Encoder.Convert(arguments);
var outputVideo = new VideoInfo(output.FullName); var outputVideo = new VideoInfo(output.FullName);

View file

@ -0,0 +1,27 @@
using FFMpegCore.FFMPEG.Enums;
namespace FFMpegCore.FFMPEG.Arguments
{
/// <summary>
/// Represents cpu speed parameter
/// </summary>
public class DisableChannelArgument : Argument<Channel>
{
public DisableChannelArgument()
{
}
public DisableChannelArgument(Channel value) : base(value)
{
}
/// <summary>
/// String representation of the argument
/// </summary>
/// <returns>String representation of the argument</returns>
public override string GetStringValue()
{
return ArgumentsStringifier.Disable(Value);
}
}
}

View file

@ -26,68 +26,13 @@ public string BuildArguments(ArgumentsContainer container)
CheckContainerException(container); CheckContainerException(container);
StringBuilder sb = new StringBuilder();
sb.Append(GetInput(container).GetStringValue().Trim() + " "); return string.Join(" ", container.Select(argument => argument.Value.GetStringValue().Trim()));
foreach(var a in container)
{
if(!IsInputOrOutput(a.Key))
{
sb.Append(a.Value.GetStringValue().Trim() + " ");
}
}
sb.Append(container[typeof(OutputArgument)].GetStringValue().Trim());
var overrideArg = container.Find<OverrideArgument>();
if (overrideArg != null)
sb.Append(" " + overrideArg.GetStringValue().Trim());
return sb.ToString();
}
/// <summary>
/// Builds parameters string from <see cref="ArgumentsContainer"/> that would be passed to ffmpeg process
/// </summary>
/// <param name="container">Container of arguments</param>
/// <param name="input">Input file</param>
/// <param name="output">Output file</param>
/// <returns>Parameters string</returns>
public string BuildArguments(ArgumentsContainer container, FileInfo input, FileInfo output)
{
CheckContainerException(container);
CheckExtensionOfOutputExtension(container, output);
FFMpegHelper.ConversionExceptionCheck(input, output);
StringBuilder sb = new StringBuilder();
var inputA = new InputArgument(input);
var outputA = new OutputArgument();
sb.Append(inputA.GetStringValue().Trim() + " ");
foreach (var a in container)
{
if (!IsInputOrOutput(a.Key))
{
sb.Append(a.Value.GetStringValue().Trim() + " ");
}
}
sb.Append(outputA.GetStringValue().Trim());
var overrideArg = container.Find<OverrideArgument>();
if (overrideArg != null)
sb.Append(" " + overrideArg.GetStringValue().Trim());
return sb.ToString();
} }
private void CheckContainerException(ArgumentsContainer container) private void CheckContainerException(ArgumentsContainer container)
{ {
//TODO: implement arguments check // TODO: implement arguments check
} }
private void CheckExtensionOfOutputExtension(ArgumentsContainer container, FileInfo output) private void CheckExtensionOfOutputExtension(ArgumentsContainer container, FileInfo output)

View file

@ -11,7 +11,5 @@ namespace FFMpegCore.FFMPEG.Arguments
public interface IArgumentBuilder public interface IArgumentBuilder
{ {
string BuildArguments(ArgumentsContainer container); string BuildArguments(ArgumentsContainer container);
string BuildArguments(ArgumentsContainer container, FileInfo input, FileInfo output);
} }
} }

View file

@ -10,25 +10,25 @@ namespace FFMpegCore.FFMPEG.Arguments
/// <summary> /// <summary>
/// Represents input parameter /// Represents input parameter
/// </summary> /// </summary>
public class InputArgument : Argument<string> public class InputArgument : Argument<string[]>
{ {
public InputArgument() public InputArgument()
{ {
} }
public InputArgument(string value) : base(value) public InputArgument(params string[] values) : base(values)
{ {
} }
public InputArgument(VideoInfo value) : base(value.FullName) public InputArgument(params VideoInfo[] values) : base(values.Select(v => v.FullName).ToArray())
{ {
} }
public InputArgument(FileInfo value) : base(value.FullName) public InputArgument(params FileInfo[] values) : base(values.Select(v => v.FullName).ToArray())
{ {
} }
public InputArgument(Uri value) : base(value.AbsolutePath) public InputArgument(params Uri[] values) : base(values.Select(v => v.AbsolutePath).ToArray())
{ {
} }
@ -38,7 +38,7 @@ public InputArgument(Uri value) : base(value.AbsolutePath)
/// <returns>String representation of the argument</returns> /// <returns>String representation of the argument</returns>
public override string GetStringValue() public override string GetStringValue()
{ {
return ArgumentsStringifier.Input(Value); return string.Join(" ", Value.Select(v => ArgumentsStringifier.Input(v)));
} }
} }
} }

View file

@ -10,7 +10,7 @@ namespace FFMpegCore.FFMPEG.Arguments
/// <summary> /// <summary>
/// Represents output parameter /// Represents output parameter
/// </summary> /// </summary>
public class OutputArgument : InputArgument public class OutputArgument : Argument<string>
{ {
public OutputArgument() public OutputArgument()
{ {
@ -20,15 +20,15 @@ public OutputArgument(string value) : base(value)
{ {
} }
public OutputArgument(VideoInfo value) : base(value) public OutputArgument(VideoInfo value) : base(value.FullName)
{ {
} }
public OutputArgument(FileInfo value) : base(value) public OutputArgument(FileInfo value) : base(value.FullName)
{ {
} }
public OutputArgument(Uri value) : base(value) public OutputArgument(Uri value) : base(value.AbsolutePath)
{ {
} }

View file

@ -9,13 +9,13 @@ namespace FFMpegCore.FFMPEG.Arguments
/// <summary> /// <summary>
/// Represents seek parameter /// Represents seek parameter
/// </summary> /// </summary>
public class SeekArgument : Argument<TimeSpan> public class SeekArgument : Argument<TimeSpan?>
{ {
public SeekArgument() public SeekArgument()
{ {
} }
public SeekArgument(TimeSpan value) : base(value) public SeekArgument(TimeSpan? value) : base(value)
{ {
} }

View file

@ -17,7 +17,7 @@ public SizeArgument()
{ {
} }
public SizeArgument(Size value) : base(value) public SizeArgument(Size? value) : base(value.HasValue ? value.Value : new Size())
{ {
} }

View file

@ -91,15 +91,15 @@ public Bitmap Snapshot(VideoInfo source, FileInfo output, Size? size = null, Tim
} }
FFMpegHelper.ConversionExceptionCheck(source.ToFileInfo(), output); FFMpegHelper.ConversionExceptionCheck(source.ToFileInfo(), output);
var container = new ArgumentsContainer();
container.Add(new InputArgument(source));
container.Add(new VideoCodecArgument(VideoCodec.Png));
container.Add(new FrameOutputCountArgument(1));
container.Add(new SeekArgument(captureTime));
container.Add(new SizeArgument(size));
container.Add(new OutputArgument(output));
var thumbArgs = ArgumentsStringifier.Input(source) + if (!RunProcess(container, output))
ArgumentsStringifier.Video(VideoCodec.Png) +
ArgumentsStringifier.FrameOutputCount(1) +
ArgumentsStringifier.Seek(captureTime) +
ArgumentsStringifier.Size(size) +
ArgumentsStringifier.Output(output);
if (!RunProcess(thumbArgs, output))
{ {
throw new OperationCanceledException("Could not take snapshot!"); throw new OperationCanceledException("Could not take snapshot!");
} }
@ -150,8 +150,6 @@ public VideoInfo Convert(
FFMpegHelper.ExtensionExceptionCheck(output, FileExtension.ForType(type)); FFMpegHelper.ExtensionExceptionCheck(output, FileExtension.ForType(type));
FFMpegHelper.ConversionSizeExceptionCheck(source); FFMpegHelper.ConversionSizeExceptionCheck(source);
string args = "";
var scale = VideoSize.Original == size ? 1 : var scale = VideoSize.Original == size ? 1 :
(double)source.Height / (int)size; (double)source.Height / (int)size;
@ -165,38 +163,38 @@ public VideoInfo Convert(
outputSize.Width += 1; outputSize.Width += 1;
} }
var container = new ArgumentsContainer();
switch (type) switch (type)
{ {
case VideoType.Mp4: case VideoType.Mp4:
container.Add(new InputArgument(source));
args = ArgumentsStringifier.Input(source) + container.Add(new ThreadsArgument(multithreaded));
ArgumentsStringifier.Threads(multithreaded) + container.Add(new ScaleArgument(outputSize));
ArgumentsStringifier.Scale(outputSize) + container.Add(new VideoCodecArgument(VideoCodec.LibX264, 2400));
ArgumentsStringifier.Video(VideoCodec.LibX264, 2400) + container.Add(new SpeedArgument(speed));
ArgumentsStringifier.Speed(speed) + container.Add(new AudioCodecArgument(AudioCodec.Aac, audioQuality));
ArgumentsStringifier.Audio(AudioCodec.Aac, audioQuality) + container.Add(new OutputArgument(output));
ArgumentsStringifier.Output(output);
break; break;
case VideoType.Ogv: case VideoType.Ogv:
args = ArgumentsStringifier.Input(source) + container.Add(new InputArgument(source));
ArgumentsStringifier.Threads(multithreaded) + container.Add(new ThreadsArgument(multithreaded));
ArgumentsStringifier.Scale(outputSize) + container.Add(new ScaleArgument(outputSize));
ArgumentsStringifier.Video(VideoCodec.LibTheora, 2400) + container.Add(new VideoCodecArgument(VideoCodec.LibTheora, 2400));
ArgumentsStringifier.Speed(16) + container.Add(new SpeedArgument(speed));
ArgumentsStringifier.Audio(AudioCodec.LibVorbis, audioQuality) + container.Add(new AudioCodecArgument(AudioCodec.LibVorbis, audioQuality));
ArgumentsStringifier.Output(output); container.Add(new OutputArgument(output));
break; break;
case VideoType.Ts: case VideoType.Ts:
args = ArgumentsStringifier.Input(source) + container.Add(new InputArgument(source));
ArgumentsStringifier.Copy() + container.Add(new CopyArgument());
ArgumentsStringifier.BitStreamFilter(Channel.Video, Filter.H264_Mp4ToAnnexB) + container.Add(new BitStreamFilterArgument(Channel.Video, Filter.H264_Mp4ToAnnexB));
ArgumentsStringifier.ForceFormat(VideoCodec.MpegTs) + container.Add(new ForceFormatArgument(VideoCodec.MpegTs));
ArgumentsStringifier.Output(output); container.Add(new OutputArgument(output));
break; break;
} }
if (!RunProcess(args, output)) if (!RunProcess(container, output))
{ {
throw new FFMpegException(FFMpegExceptionType.Conversion, $"The video could not be converted to {Enum.GetName(typeof(VideoType), type)}"); throw new FFMpegException(FFMpegExceptionType.Conversion, $"The video could not be converted to {Enum.GetName(typeof(VideoType), type)}");
} }
@ -217,15 +215,15 @@ public VideoInfo PosterWithAudio(FileInfo image, FileInfo audio, FileInfo output
FFMpegHelper.ExtensionExceptionCheck(output, FileExtension.Mp4); FFMpegHelper.ExtensionExceptionCheck(output, FileExtension.Mp4);
FFMpegHelper.ConversionSizeExceptionCheck(Image.FromFile(image.FullName)); FFMpegHelper.ConversionSizeExceptionCheck(Image.FromFile(image.FullName));
var args = ArgumentsStringifier.Loop(1) + var container = new ArgumentsContainer();
ArgumentsStringifier.Input(image) + container.Add(new LoopArgument(1));
ArgumentsStringifier.Input(audio) + container.Add(new InputArgument(image.FullName, audio.FullName));
ArgumentsStringifier.Video(VideoCodec.LibX264, 2400) + container.Add(new VideoCodecArgument(VideoCodec.LibX264, 2400));
ArgumentsStringifier.Audio(AudioCodec.Aac, AudioQuality.Normal) + container.Add(new AudioCodecArgument(AudioCodec.Aac, AudioQuality.Normal));
ArgumentsStringifier.FinalizeAtShortestInput(true) + container.Add(new ShortestArgument(true));
ArgumentsStringifier.Output(output); container.Add(new OutputArgument(output));
if (!RunProcess(args, output)) if (!RunProcess(container, output))
{ {
throw new FFMpegException(FFMpegExceptionType.Operation, "An error occured while adding the audio file to the image."); throw new FFMpegException(FFMpegExceptionType.Operation, "An error occured while adding the audio file to the image.");
} }
@ -256,14 +254,15 @@ public VideoInfo Join(FileInfo output, params VideoInfo[] videos)
return destinationPath; return destinationPath;
}).ToList(); }).ToList();
var args = ArgumentsStringifier.InputConcat(temporaryVideoParts) + var container = new ArgumentsContainer();
ArgumentsStringifier.Copy() + container.Add(new ConcatArgument(temporaryVideoParts));
ArgumentsStringifier.BitStreamFilter(Channel.Audio, Filter.Aac_AdtstoAsc) + container.Add(new CopyArgument());
ArgumentsStringifier.Output(output); container.Add(new BitStreamFilterArgument(Channel.Audio, Filter.Aac_AdtstoAsc));
container.Add(new OutputArgument(output));
try try
{ {
if (!RunProcess(args, output)) if (!RunProcess(container, output))
{ {
throw new FFMpegException(FFMpegExceptionType.Operation, "Could not join the provided video files."); throw new FFMpegException(FFMpegExceptionType.Operation, "Could not join the provided video files.");
} }
@ -296,17 +295,18 @@ public VideoInfo JoinImageSequence(FileInfo output, double frameRate = 30, param
var firstImage = images.First(); var firstImage = images.First();
var args = ArgumentsStringifier.FrameRate(frameRate) + var container = new ArgumentsContainer();
ArgumentsStringifier.Size(new Size(firstImage.Width, firstImage.Height)) + container.Add(new FrameRateArgument(frameRate));
ArgumentsStringifier.StartNumber(0) + container.Add(new SizeArgument(firstImage.Width, firstImage.Height));
ArgumentsStringifier.Input($"{firstImage.Directory}\\%09d.png") + container.Add(new StartNumberArgument(0));
ArgumentsStringifier.FrameOutputCount(images.Length) + container.Add(new InputArgument($"{firstImage.Directory}\\%09d.png"));
ArgumentsStringifier.Video(VideoCodec.LibX264) + container.Add(new FrameOutputCountArgument(images.Length));
ArgumentsStringifier.Output(output); container.Add(new VideoCodecArgument(VideoCodec.LibX264));
container.Add(new OutputArgument(output));
try try
{ {
if (!RunProcess(args, output)) if (!RunProcess(container, output))
{ {
throw new FFMpegException(FFMpegExceptionType.Operation, "Could not join the provided image sequence."); throw new FFMpegException(FFMpegExceptionType.Operation, "Could not join the provided image sequence.");
} }
@ -331,10 +331,11 @@ public VideoInfo SaveM3U8Stream(Uri uri, FileInfo output)
if (uri.Scheme == "http" || uri.Scheme == "https") if (uri.Scheme == "http" || uri.Scheme == "https")
{ {
var args = ArgumentsStringifier.Input(uri) + var container = new ArgumentsContainer();
ArgumentsStringifier.Output(output); container.Add(new InputArgument(uri));
container.Add(new OutputArgument(output));
if (!RunProcess(args, output)) if (!RunProcess(container, output))
{ {
throw new FFMpegException(FFMpegExceptionType.Operation, $"Saving the ${uri.AbsoluteUri} stream failed."); throw new FFMpegException(FFMpegExceptionType.Operation, $"Saving the ${uri.AbsoluteUri} stream failed.");
} }
@ -356,12 +357,13 @@ public VideoInfo Mute(VideoInfo source, FileInfo output)
FFMpegHelper.ConversionSizeExceptionCheck(source); FFMpegHelper.ConversionSizeExceptionCheck(source);
FFMpegHelper.ExtensionExceptionCheck(output, source.Extension); FFMpegHelper.ExtensionExceptionCheck(output, source.Extension);
var args = ArgumentsStringifier.Input(source) + var container = new ArgumentsContainer();
ArgumentsStringifier.Copy() + container.Add(new InputArgument(source));
ArgumentsStringifier.Disable(Channel.Audio) + container.Add(new CopyArgument());
ArgumentsStringifier.Output(output); container.Add(new DisableChannelArgument(Channel.Audio));
container.Add(new OutputArgument(output));
if (!RunProcess(args, output)) if (!RunProcess(container, output))
{ {
throw new FFMpegException(FFMpegExceptionType.Operation, "Could not mute the requested video."); throw new FFMpegException(FFMpegExceptionType.Operation, "Could not mute the requested video.");
} }
@ -380,11 +382,12 @@ public FileInfo ExtractAudio(VideoInfo source, FileInfo output)
FFMpegHelper.ConversionExceptionCheck(source.ToFileInfo(), output); FFMpegHelper.ConversionExceptionCheck(source.ToFileInfo(), output);
FFMpegHelper.ExtensionExceptionCheck(output, FileExtension.Mp3); FFMpegHelper.ExtensionExceptionCheck(output, FileExtension.Mp3);
var args = ArgumentsStringifier.Input(source) + var container = new ArgumentsContainer();
ArgumentsStringifier.Disable(Channel.Video) + container.Add(new InputArgument(source));
ArgumentsStringifier.Output(output); container.Add(new DisableChannelArgument(Channel.Video));
container.Add(new OutputArgument(output));
if (!RunProcess(args, output)) if (!RunProcess(container, output))
{ {
throw new FFMpegException(FFMpegExceptionType.Operation, "Could not extract the audio from the requested video."); throw new FFMpegException(FFMpegExceptionType.Operation, "Could not extract the audio from the requested video.");
} }
@ -409,14 +412,15 @@ public VideoInfo ReplaceAudio(VideoInfo source, FileInfo audio, FileInfo output,
FFMpegHelper.ConversionSizeExceptionCheck(source); FFMpegHelper.ConversionSizeExceptionCheck(source);
FFMpegHelper.ExtensionExceptionCheck(output, source.Extension); FFMpegHelper.ExtensionExceptionCheck(output, source.Extension);
var args = ArgumentsStringifier.Input(source) + var container = new ArgumentsContainer();
ArgumentsStringifier.Input(audio) + container.Add(new InputArgument(source.FullName, audio.FullName));
ArgumentsStringifier.Copy(Channel.Video) + //container.Add(new InputArgument(audio));
ArgumentsStringifier.Audio(AudioCodec.Aac, AudioQuality.Hd) + container.Add(new CopyArgument());
ArgumentsStringifier.FinalizeAtShortestInput(stopAtShortest) + container.Add(new AudioCodecArgument(AudioCodec.Aac, AudioQuality.Hd));
ArgumentsStringifier.Output(output); container.Add(new ShortestArgument(stopAtShortest));
container.Add(new OutputArgument(output));
if (!RunProcess(args, output)) if (!RunProcess(container, output))
{ {
throw new FFMpegException(FFMpegExceptionType.Operation, "Could not replace the video audio."); throw new FFMpegException(FFMpegExceptionType.Operation, "Could not replace the video audio.");
} }
@ -429,19 +433,7 @@ public VideoInfo Convert(ArgumentsContainer arguments)
var args = argumentBuilder.BuildArguments(arguments); var args = argumentBuilder.BuildArguments(arguments);
var output = ((OutputArgument)arguments[typeof(OutputArgument)]).GetAsFileInfo(); var output = ((OutputArgument)arguments[typeof(OutputArgument)]).GetAsFileInfo();
if (!RunProcess(args, output)) if (!RunProcess(arguments, output))
{
throw new FFMpegException(FFMpegExceptionType.Operation, "Could not replace the video audio.");
}
return new VideoInfo(output);
}
public VideoInfo Convert(ArgumentsContainer arguments, FileInfo input, FileInfo output)
{
var args = argumentBuilder.BuildArguments(arguments, input, output);
if (!RunProcess(args, output))
{ {
throw new FFMpegException(FFMpegExceptionType.Operation, "Could not replace the video audio."); throw new FFMpegException(FFMpegExceptionType.Operation, "Could not replace the video audio.");
} }
@ -467,11 +459,11 @@ public void Stop()
private volatile StringBuilder _errorOutput = new StringBuilder(); private volatile StringBuilder _errorOutput = new StringBuilder();
private bool RunProcess(string args, FileInfo output) private bool RunProcess(ArgumentsContainer container, FileInfo output)
{ {
var successState = true; var successState = true;
CreateProcess(args, _ffmpegPath, true, rStandardError: true); CreateProcess(this.argumentBuilder.BuildArguments(container), _ffmpegPath, true, rStandardError: true);
try try
{ {