Merge branch 'master' into features/raw-argument

This commit is contained in:
Weihan Li 2020-05-02 11:07:04 +08:00 committed by GitHub
commit 1688e0d6e4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 62 additions and 28 deletions

View file

@ -50,8 +50,22 @@ public void Builder_BuildString_Scale()
[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));
Assert.AreEqual(str, "-i \"input.mp4\" -c:a aac -b:a 128k \"output.mp4\""); 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] [TestMethod]

View file

@ -0,0 +1,19 @@
using FFMpegCore.FFMPEG.Enums;
namespace FFMpegCore.FFMPEG.Argument
{
/// <summary>
/// Represents parameter of audio codec and it's quality
/// </summary>
public class AudioBitrateArgument : Argument<int>
{
public AudioBitrateArgument(AudioQuality value) : base((int)value) { }
public AudioBitrateArgument(int bitrate) : base(bitrate) { }
/// <inheritdoc/>
public override string GetStringValue()
{
return $"-b:a {Value}k";
}
}
}

View file

@ -7,26 +7,12 @@ namespace FFMpegCore.FFMPEG.Argument
/// </summary> /// </summary>
public class AudioCodecArgument : Argument<AudioCodec> public class AudioCodecArgument : Argument<AudioCodec>
{ {
/// <summary>
/// Bitrate of audio channel
/// </summary>
public int Bitrate { get; } = (int)AudioQuality.Normal;
public AudioCodecArgument() { }
public AudioCodecArgument(AudioCodec value) : base(value) { } 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;
}
/// <inheritdoc/> /// <inheritdoc/>
public override string GetStringValue() public override string GetStringValue()
{ {
return $"-c:a {Value.ToString().ToLower()} -b:a {Bitrate}k"; return $"-c:a {Value.ToString().ToLower()}";
} }
} }
} }

View file

@ -0,0 +1,10 @@
namespace FFMpegCore.FFMPEG.Argument
{
public class QuietArgument : Argument
{
public override string GetStringValue()
{
return "-hide_banner -loglevel warning";
}
}
}

View file

@ -149,7 +149,8 @@ public VideoInfo Convert(
new ScaleArgument(outputSize), new ScaleArgument(outputSize),
new VideoCodecArgument(VideoCodec.LibX264, 2400), new VideoCodecArgument(VideoCodec.LibX264, 2400),
new SpeedArgument(speed), new SpeedArgument(speed),
new AudioCodecArgument(AudioCodec.Aac, audioQuality), new AudioCodecArgument(AudioCodec.Aac),
new AudioBitrateArgument(audioQuality),
new OutputArgument(output))), new OutputArgument(output))),
VideoType.Ogv => Convert(new ArgumentContainer( VideoType.Ogv => Convert(new ArgumentContainer(
new InputArgument(source), new InputArgument(source),
@ -157,7 +158,8 @@ public VideoInfo Convert(
new ScaleArgument(outputSize), new ScaleArgument(outputSize),
new VideoCodecArgument(VideoCodec.LibTheora, 2400), new VideoCodecArgument(VideoCodec.LibTheora, 2400),
new SpeedArgument(speed), new SpeedArgument(speed),
new AudioCodecArgument(AudioCodec.LibVorbis, audioQuality), new AudioCodecArgument(AudioCodec.LibVorbis),
new AudioBitrateArgument(audioQuality),
new OutputArgument(output))), new OutputArgument(output))),
VideoType.Ts => Convert(new ArgumentContainer( VideoType.Ts => Convert(new ArgumentContainer(
new InputArgument(source), new InputArgument(source),
@ -171,7 +173,8 @@ public VideoInfo Convert(
new ScaleArgument(outputSize), new ScaleArgument(outputSize),
new VideoCodecArgument(VideoCodec.LibVpx, 2400), new VideoCodecArgument(VideoCodec.LibVpx, 2400),
new SpeedArgument(speed), new SpeedArgument(speed),
new AudioCodecArgument(AudioCodec.LibVorbis, audioQuality), new AudioCodecArgument(AudioCodec.LibVorbis),
new AudioBitrateArgument(audioQuality),
new OutputArgument(output))), new OutputArgument(output))),
_ => throw new ArgumentOutOfRangeException(nameof(type)) _ => 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 InputArgument(image.FullName, audio.FullName),
new LoopArgument(1), new LoopArgument(1),
new VideoCodecArgument(VideoCodec.LibX264, 2400), new VideoCodecArgument(VideoCodec.LibX264, 2400),
new AudioCodecArgument(AudioCodec.Aac, AudioQuality.Normal), new AudioCodecArgument(AudioCodec.Aac),
new AudioBitrateArgument(AudioQuality.Normal),
new ShortestArgument(true), new ShortestArgument(true),
new OutputArgument(output) new OutputArgument(output)
); );
@ -375,7 +379,8 @@ public VideoInfo ReplaceAudio(VideoInfo source, FileInfo audio, FileInfo output,
return Convert(new ArgumentContainer( return Convert(new ArgumentContainer(
new InputArgument(source.FullName, audio.FullName), new InputArgument(source.FullName, audio.FullName),
new CopyArgument(), new CopyArgument(),
new AudioCodecArgument(AudioCodec.Aac, AudioQuality.Hd), new AudioCodecArgument(AudioCodec.Aac),
new AudioBitrateArgument(AudioQuality.Hd),
new ShortestArgument(stopAtShortest), new ShortestArgument(stopAtShortest),
new OutputArgument(output) 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"); throw new FFMpegException(FFMpegExceptionType.Conversion, "Could not process file without error");
_totalTime = TimeSpan.MinValue; _totalTime = TimeSpan.MinValue;
return new VideoInfo(output); return output.Exists ? new VideoInfo(output) : null;
} }
public async Task<VideoInfo> ConvertAsync(ArgumentContainer arguments, bool skipExistsCheck = false) public async Task<VideoInfo> ConvertAsync(ArgumentContainer arguments, bool skipExistsCheck = false)
{ {
@ -401,7 +406,7 @@ public async Task<VideoInfo> ConvertAsync(ArgumentContainer arguments, bool skip
throw new FFMpegException(FFMpegExceptionType.Conversion, "Could not process file without error"); throw new FFMpegException(FFMpegExceptionType.Conversion, "Could not process file without error");
_totalTime = TimeSpan.MinValue; _totalTime = TimeSpan.MinValue;
return new VideoInfo(output); return output.Exists ? new VideoInfo(output) : null;
} }
private static (VideoInfo[] Input, FileInfo Output) GetInputOutput(ArgumentContainer arguments) private static (VideoInfo[] Input, FileInfo Output) GetInputOutput(ArgumentContainer arguments)

View file

@ -72,7 +72,7 @@ private VideoInfo ParseVideoInfoInternal(VideoInfo info, string probeOutput)
{ {
var metadata = JsonConvert.DeserializeObject<FFMpegStreamMetadata>(probeOutput); var metadata = JsonConvert.DeserializeObject<FFMpegStreamMetadata>(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}"); throw new FFMpegException(FFMpegExceptionType.File, $"No video or audio streams could be detected. Source: ${info.FullName}");
} }

View file

@ -358,9 +358,9 @@ public enum VideoCodec
} }
``` ```
### ArgumentBuilder ### 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 ```csharp
var container = new ArgumentsContainer(); var container = new ArgumentContainer();
container.Add(new VideoCodecArgument(VideoCodec.LibX264)); container.Add(new VideoCodecArgument(VideoCodec.LibX264));
container.Add(new ScaleArgument(VideoSize.Hd)); 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")); 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<T>` or `Argument<T1, T2>` If you need to create your custom argument, you just need to create new class, that is inherited from `Argument`, `Argument<T>` or `Argument<T1, T2>`
For example: For example: