From 93dd3b4264f24450a5636da14ec11453f96b60c8 Mon Sep 17 00:00:00 2001 From: Weihan Li Date: Tue, 28 Apr 2020 10:52:03 +0800 Subject: [PATCH 1/3] 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 985fc0cbc46cd57dc3f1f370145d118c00f975a4 Mon Sep 17 00:00:00 2001 From: weihanli Date: Tue, 28 Apr 2020 19:40:31 +0800 Subject: [PATCH 2/3] 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 3/3] 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}"); }