From 93dd3b4264f24450a5636da14ec11453f96b60c8 Mon Sep 17 00:00:00 2001 From: Weihan Li Date: Tue, 28 Apr 2020 10:52:03 +0800 Subject: [PATCH 1/5] fix ArgumentContainer Former-commit-id: 1458a9d0641664929b08228a9f1cca33d88d8f3e --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 6fddd05..e95d25c 100644 --- a/README.md +++ b/README.md @@ -358,9 +358,9 @@ public enum VideoCodec } ``` ### ArgumentBuilder -Custom video converting presets could be created with help of `ArgumentsContainer` class: +Custom video converting presets could be created with help of `ArgumentContainer` class: ```csharp -var container = new ArgumentsContainer(); +var container = new ArgumentContainer(); container.Add(new VideoCodecArgument(VideoCodec.LibX264)); container.Add(new ScaleArgument(VideoSize.Hd)); @@ -368,7 +368,7 @@ var ffmpeg = new FFMpeg(); var result = ffmpeg.Convert(container, new FileInfo("input.mp4"), new FileInfo("output.mp4")); ``` -Other availible arguments could be found in `FFMpegCore.FFMPEG.Arguments` namespace. +Other availible arguments could be found in `FFMpegCore.FFMPEG.Argument` namespace. If you need to create your custom argument, you just need to create new class, that is inherited from `Argument`, `Argument` or `Argument` For example: From 9ffa2cb28a5968c1855cb1ee3beb931e9c6c4400 Mon Sep 17 00:00:00 2001 From: weihanli Date: Tue, 28 Apr 2020 12:26:42 +0800 Subject: [PATCH 2/5] add RawArgument.cs Former-commit-id: 5643544a3b7ff082f84285df1014856f85a511c6 --- FFMpegCore.Test/ArgumentBuilderTest.cs | 31 ++++++++++++------- .../FFMPEG/Argument/Atoms/RawArgument.cs | 14 +++++++++ 2 files changed, 33 insertions(+), 12 deletions(-) create mode 100644 FFMpegCore/FFMPEG/Argument/Atoms/RawArgument.cs diff --git a/FFMpegCore.Test/ArgumentBuilderTest.cs b/FFMpegCore.Test/ArgumentBuilderTest.cs index cde8da2..38066c5 100644 --- a/FFMpegCore.Test/ArgumentBuilderTest.cs +++ b/FFMpegCore.Test/ArgumentBuilderTest.cs @@ -9,10 +9,10 @@ namespace FFMpegCore.Test [TestClass] public class ArgumentBuilderTest : BaseTest { - List concatFiles = new List + private List concatFiles = new List { "1.mp4", "2.mp4", "3.mp4", "4.mp4"}; - FFArgumentBuilder builder; + private FFArgumentBuilder builder; public ArgumentBuilderTest() : base() { @@ -21,7 +21,7 @@ public ArgumentBuilderTest() : base() private string GetArgumentsString(params Argument[] args) { - var container = new ArgumentContainer {new InputArgument("input.mp4")}; + var container = new ArgumentContainer { new InputArgument("input.mp4") }; foreach (var a in args) { container.Add(a); @@ -31,7 +31,6 @@ private string GetArgumentsString(params Argument[] args) return builder.BuildArguments(container); } - [TestMethod] public void Builder_BuildString_IO_1() { @@ -66,8 +65,7 @@ public void Builder_BuildString_BitStream() [TestMethod] public void Builder_BuildString_Concat() { - var container = new ArgumentContainer {new ConcatArgument(concatFiles), new OutputArgument("output.mp4")}; - + var container = new ArgumentContainer { new ConcatArgument(concatFiles), new OutputArgument("output.mp4") }; var str = builder.BuildArguments(container); @@ -82,7 +80,6 @@ public void Builder_BuildString_Copy_Audio() Assert.AreEqual(str, "-i \"input.mp4\" -c:a copy \"output.mp4\""); } - [TestMethod] public void Builder_BuildString_Copy_Video() { @@ -174,7 +171,7 @@ public void Builder_BuildString_Speed() [TestMethod] public void Builder_BuildString_DrawtextFilter() { - var str = GetArgumentsString(new DrawTextArgument("Stack Overflow", "/path/to/font.ttf", + var str = GetArgumentsString(new DrawTextArgument("Stack Overflow", "/path/to/font.ttf", ("fontcolor", "white"), ("fontsize", "24"), ("box", "1"), @@ -198,7 +195,7 @@ public void Builder_BuildString_StartNumber() public void Builder_BuildString_Threads_1() { var str = GetArgumentsString(new ThreadsArgument(50)); - + Assert.AreEqual(str, "-i \"input.mp4\" -threads 50 \"output.mp4\""); } @@ -210,7 +207,6 @@ public void Builder_BuildString_Threads_2() Assert.AreEqual(str, $"-i \"input.mp4\" -threads {Environment.ProcessorCount} \"output.mp4\""); } - [TestMethod] public void Builder_BuildString_Codec() { @@ -228,10 +224,21 @@ public void Builder_BuildString_Codec_Override() } [TestMethod] - public void Builder_BuildString_Duration() { + public void Builder_BuildString_Duration() + { var str = GetArgumentsString(new DurationArgument(TimeSpan.FromSeconds(20))); Assert.AreEqual(str, "-i \"input.mp4\" -t 00:00:20 \"output.mp4\""); } + + [TestMethod] + public void Builder_BuildString_Raw() + { + var str = GetArgumentsString(new RawArgument(null)); + Assert.AreEqual(str, "-i \"input.mp4\" \"output.mp4\""); + + str = GetArgumentsString(new RawArgument("-acodec copy")); + Assert.AreEqual(str, "-i \"input.mp4\" -acodec copy \"output.mp4\""); + } } -} +} \ No newline at end of file diff --git a/FFMpegCore/FFMPEG/Argument/Atoms/RawArgument.cs b/FFMpegCore/FFMPEG/Argument/Atoms/RawArgument.cs new file mode 100644 index 0000000..74a9df6 --- /dev/null +++ b/FFMpegCore/FFMPEG/Argument/Atoms/RawArgument.cs @@ -0,0 +1,14 @@ +namespace FFMpegCore.FFMPEG.Argument +{ + public class RawArgument : Argument + { + public RawArgument(string argument) : base(argument) + { + } + + public override string GetStringValue() + { + return Value ?? string.Empty; + } + } +} \ No newline at end of file From 985fc0cbc46cd57dc3f1f370145d118c00f975a4 Mon Sep 17 00:00:00 2001 From: weihanli Date: Tue, 28 Apr 2020 19:40:31 +0800 Subject: [PATCH 3/5] return null when file not exits Former-commit-id: 1e24b0bef46adeb80107c76079ea840c4a70dbbb --- FFMpegCore/FFMPEG/FFMpeg.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/FFMpegCore/FFMPEG/FFMpeg.cs b/FFMpegCore/FFMPEG/FFMpeg.cs index 8f2c1a3..15601a0 100644 --- a/FFMpegCore/FFMPEG/FFMpeg.cs +++ b/FFMpegCore/FFMPEG/FFMpeg.cs @@ -390,7 +390,7 @@ public VideoInfo Convert(ArgumentContainer arguments, bool skipExistsCheck = fal throw new FFMpegException(FFMpegExceptionType.Conversion, "Could not process file without error"); _totalTime = TimeSpan.MinValue; - return new VideoInfo(output); + return output.Exists ? new VideoInfo(output) : null; } public async Task ConvertAsync(ArgumentContainer arguments, bool skipExistsCheck = false) { @@ -401,7 +401,7 @@ public async Task ConvertAsync(ArgumentContainer arguments, bool skip throw new FFMpegException(FFMpegExceptionType.Conversion, "Could not process file without error"); _totalTime = TimeSpan.MinValue; - return new VideoInfo(output); + return output.Exists ? new VideoInfo(output) : null; } private static (VideoInfo[] Input, FileInfo Output) GetInputOutput(ArgumentContainer arguments) From 78e3f5e0c5613a84999df57939e0102c2fe56e16 Mon Sep 17 00:00:00 2001 From: Malte Rosenbjerg Date: Fri, 1 May 2020 10:07:40 +0200 Subject: [PATCH 4/5] Add AudioBitrate as separate Argument Former-commit-id: 4b88229f72ac7fc93aa1abd3e6841d67489de8e8 --- FFMpegCore.Test/ArgumentBuilderTest.cs | 18 ++++++++++++++++-- .../Argument/Atoms/AudioBitrateArgument.cs | 19 +++++++++++++++++++ .../Argument/Atoms/AudioCodecArgument.cs | 16 +--------------- .../FFMPEG/Argument/Atoms/QuietArgument.cs | 10 ++++++++++ FFMpegCore/FFMPEG/FFMpeg.cs | 15 ++++++++++----- FFMpegCore/FFMPEG/FFProbe.cs | 2 +- 6 files changed, 57 insertions(+), 23 deletions(-) create mode 100644 FFMpegCore/FFMPEG/Argument/Atoms/AudioBitrateArgument.cs create mode 100644 FFMpegCore/FFMPEG/Argument/Atoms/QuietArgument.cs diff --git a/FFMpegCore.Test/ArgumentBuilderTest.cs b/FFMpegCore.Test/ArgumentBuilderTest.cs index cde8da2..687c76e 100644 --- a/FFMpegCore.Test/ArgumentBuilderTest.cs +++ b/FFMpegCore.Test/ArgumentBuilderTest.cs @@ -51,8 +51,22 @@ public void Builder_BuildString_Scale() [TestMethod] public void Builder_BuildString_AudioCodec() { - var str = GetArgumentsString(new AudioCodecArgument(AudioCodec.Aac, AudioQuality.Normal)); - Assert.AreEqual(str, "-i \"input.mp4\" -c:a aac -b:a 128k \"output.mp4\""); + var str = GetArgumentsString(new AudioCodecArgument(AudioCodec.Aac)); + Assert.AreEqual(str, "-i \"input.mp4\" -c:a aac \"output.mp4\""); + } + + [TestMethod] + public void Builder_BuildString_AudioBitrate() + { + var str = GetArgumentsString(new AudioBitrateArgument(AudioQuality.Normal)); + Assert.AreEqual(str, "-i \"input.mp4\" -b:a 128k \"output.mp4\""); + } + + [TestMethod] + public void Builder_BuildString_Quiet() + { + var str = GetArgumentsString(new QuietArgument()); + Assert.AreEqual(str, "-i \"input.mp4\" -hide_banner -loglevel warning \"output.mp4\""); } [TestMethod] diff --git a/FFMpegCore/FFMPEG/Argument/Atoms/AudioBitrateArgument.cs b/FFMpegCore/FFMPEG/Argument/Atoms/AudioBitrateArgument.cs new file mode 100644 index 0000000..7ecde09 --- /dev/null +++ b/FFMpegCore/FFMPEG/Argument/Atoms/AudioBitrateArgument.cs @@ -0,0 +1,19 @@ +using FFMpegCore.FFMPEG.Enums; + +namespace FFMpegCore.FFMPEG.Argument +{ + /// + /// Represents parameter of audio codec and it's quality + /// + public class AudioBitrateArgument : Argument + { + public AudioBitrateArgument(AudioQuality value) : base((int)value) { } + public AudioBitrateArgument(int bitrate) : base(bitrate) { } + + /// + public override string GetStringValue() + { + return $"-b:a {Value}k"; + } + } +} \ No newline at end of file diff --git a/FFMpegCore/FFMPEG/Argument/Atoms/AudioCodecArgument.cs b/FFMpegCore/FFMPEG/Argument/Atoms/AudioCodecArgument.cs index 7cdb6c5..9c75386 100644 --- a/FFMpegCore/FFMPEG/Argument/Atoms/AudioCodecArgument.cs +++ b/FFMpegCore/FFMPEG/Argument/Atoms/AudioCodecArgument.cs @@ -7,26 +7,12 @@ namespace FFMpegCore.FFMPEG.Argument /// public class AudioCodecArgument : Argument { - /// - /// Bitrate of audio channel - /// - public int Bitrate { get; } = (int)AudioQuality.Normal; - - public AudioCodecArgument() { } - public AudioCodecArgument(AudioCodec value) : base(value) { } - public AudioCodecArgument(AudioCodec value, AudioQuality bitrate) : this(value, (int) bitrate) { } - - public AudioCodecArgument(AudioCodec value, int bitrate) : base(value) - { - Bitrate = bitrate; - } - /// public override string GetStringValue() { - return $"-c:a {Value.ToString().ToLower()} -b:a {Bitrate}k"; + return $"-c:a {Value.ToString().ToLower()}"; } } } diff --git a/FFMpegCore/FFMPEG/Argument/Atoms/QuietArgument.cs b/FFMpegCore/FFMPEG/Argument/Atoms/QuietArgument.cs new file mode 100644 index 0000000..a5d5c2e --- /dev/null +++ b/FFMpegCore/FFMPEG/Argument/Atoms/QuietArgument.cs @@ -0,0 +1,10 @@ +namespace FFMpegCore.FFMPEG.Argument +{ + public class QuietArgument : Argument + { + public override string GetStringValue() + { + return "-hide_banner -loglevel warning"; + } + } +} \ No newline at end of file diff --git a/FFMpegCore/FFMPEG/FFMpeg.cs b/FFMpegCore/FFMPEG/FFMpeg.cs index 8f2c1a3..a7a9ddc 100644 --- a/FFMpegCore/FFMPEG/FFMpeg.cs +++ b/FFMpegCore/FFMPEG/FFMpeg.cs @@ -149,7 +149,8 @@ public VideoInfo Convert( new ScaleArgument(outputSize), new VideoCodecArgument(VideoCodec.LibX264, 2400), new SpeedArgument(speed), - new AudioCodecArgument(AudioCodec.Aac, audioQuality), + new AudioCodecArgument(AudioCodec.Aac), + new AudioBitrateArgument(audioQuality), new OutputArgument(output))), VideoType.Ogv => Convert(new ArgumentContainer( new InputArgument(source), @@ -157,7 +158,8 @@ public VideoInfo Convert( new ScaleArgument(outputSize), new VideoCodecArgument(VideoCodec.LibTheora, 2400), new SpeedArgument(speed), - new AudioCodecArgument(AudioCodec.LibVorbis, audioQuality), + new AudioCodecArgument(AudioCodec.LibVorbis), + new AudioBitrateArgument(audioQuality), new OutputArgument(output))), VideoType.Ts => Convert(new ArgumentContainer( new InputArgument(source), @@ -171,7 +173,8 @@ public VideoInfo Convert( new ScaleArgument(outputSize), new VideoCodecArgument(VideoCodec.LibVpx, 2400), new SpeedArgument(speed), - new AudioCodecArgument(AudioCodec.LibVorbis, audioQuality), + new AudioCodecArgument(AudioCodec.LibVorbis), + new AudioBitrateArgument(audioQuality), new OutputArgument(output))), _ => throw new ArgumentOutOfRangeException(nameof(type)) }; @@ -194,7 +197,8 @@ public VideoInfo PosterWithAudio(FileInfo image, FileInfo audio, FileInfo output new InputArgument(image.FullName, audio.FullName), new LoopArgument(1), new VideoCodecArgument(VideoCodec.LibX264, 2400), - new AudioCodecArgument(AudioCodec.Aac, AudioQuality.Normal), + new AudioCodecArgument(AudioCodec.Aac), + new AudioBitrateArgument(AudioQuality.Normal), new ShortestArgument(true), new OutputArgument(output) ); @@ -375,7 +379,8 @@ public VideoInfo ReplaceAudio(VideoInfo source, FileInfo audio, FileInfo output, return Convert(new ArgumentContainer( new InputArgument(source.FullName, audio.FullName), new CopyArgument(), - new AudioCodecArgument(AudioCodec.Aac, AudioQuality.Hd), + new AudioCodecArgument(AudioCodec.Aac), + new AudioBitrateArgument(AudioQuality.Hd), new ShortestArgument(stopAtShortest), new OutputArgument(output) )); diff --git a/FFMpegCore/FFMPEG/FFProbe.cs b/FFMpegCore/FFMPEG/FFProbe.cs index 52cb0b8..d1f0a3c 100644 --- a/FFMpegCore/FFMPEG/FFProbe.cs +++ b/FFMpegCore/FFMPEG/FFProbe.cs @@ -72,7 +72,7 @@ private VideoInfo ParseVideoInfoInternal(VideoInfo info, string probeOutput) { var metadata = JsonConvert.DeserializeObject(probeOutput); - if (metadata.Streams == null || metadata.Streams.Count == 0) + if (metadata?.Streams == null || metadata.Streams.Count == 0) { throw new FFMpegException(FFMpegExceptionType.File, $"No video or audio streams could be detected. Source: ${info.FullName}"); } From 5a6d61cfe3da3be8ec029e4758ba661fbb86f162 Mon Sep 17 00:00:00 2001 From: weihanli Date: Sat, 2 May 2020 11:05:44 +0800 Subject: [PATCH 5/5] rename RawArgument to CustomArgument Former-commit-id: eb521ae908874e3216ea5555cb042b57b612e0f5 --- FFMpegCore.Test/ArgumentBuilderTest.cs | 4 ++-- .../Argument/Atoms/{RawArgument.cs => CustomArgument.cs} | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) rename FFMpegCore/FFMPEG/Argument/Atoms/{RawArgument.cs => CustomArgument.cs} (61%) diff --git a/FFMpegCore.Test/ArgumentBuilderTest.cs b/FFMpegCore.Test/ArgumentBuilderTest.cs index 38066c5..23a66f2 100644 --- a/FFMpegCore.Test/ArgumentBuilderTest.cs +++ b/FFMpegCore.Test/ArgumentBuilderTest.cs @@ -234,10 +234,10 @@ public void Builder_BuildString_Duration() [TestMethod] public void Builder_BuildString_Raw() { - var str = GetArgumentsString(new RawArgument(null)); + var str = GetArgumentsString(new CustomArgument(null)); Assert.AreEqual(str, "-i \"input.mp4\" \"output.mp4\""); - str = GetArgumentsString(new RawArgument("-acodec copy")); + str = GetArgumentsString(new CustomArgument("-acodec copy")); Assert.AreEqual(str, "-i \"input.mp4\" -acodec copy \"output.mp4\""); } } diff --git a/FFMpegCore/FFMPEG/Argument/Atoms/RawArgument.cs b/FFMpegCore/FFMPEG/Argument/Atoms/CustomArgument.cs similarity index 61% rename from FFMpegCore/FFMPEG/Argument/Atoms/RawArgument.cs rename to FFMpegCore/FFMPEG/Argument/Atoms/CustomArgument.cs index 74a9df6..6a38b4e 100644 --- a/FFMpegCore/FFMPEG/Argument/Atoms/RawArgument.cs +++ b/FFMpegCore/FFMPEG/Argument/Atoms/CustomArgument.cs @@ -1,8 +1,8 @@ namespace FFMpegCore.FFMPEG.Argument { - public class RawArgument : Argument + public class CustomArgument : Argument { - public RawArgument(string argument) : base(argument) + public CustomArgument(string argument) : base(argument) { }