diff --git a/FFMpegCore.Test/ArgumentBuilderTest.cs b/FFMpegCore.Test/ArgumentBuilderTest.cs index 23a66f2..08be2f8 100644 --- a/FFMpegCore.Test/ArgumentBuilderTest.cs +++ b/FFMpegCore.Test/ArgumentBuilderTest.cs @@ -50,8 +50,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..e3efe40 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) )); @@ -390,7 +395,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 +406,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) 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}"); } 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: