mirror of
https://github.com/revenz/FileFlowsPlugins.git
synced 2026-05-06 16:59:22 -05:00
FF-1165 - new flow element for bitrate encoding videos
This commit is contained in:
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,79 @@
|
||||
using FileFlows.VideoNodes.Helpers;
|
||||
|
||||
namespace FileFlows.VideoNodes.FfmpegBuilderNodes;
|
||||
|
||||
public partial class FfmpegBuilderVideoBitrateEncode
|
||||
{
|
||||
/// <summary>
|
||||
/// AV1 CPU encoding
|
||||
/// </summary>
|
||||
/// <param name="bitrate">the bitrate in Kbps</param>
|
||||
/// <returns>the encoding parameters</returns>
|
||||
private static IEnumerable<string> AV1_CPU(int bitrate)
|
||||
{
|
||||
return new []
|
||||
{
|
||||
//"libaom-av1",
|
||||
"libsvtav1",
|
||||
"-b:v:{index}", bitrate + "k",
|
||||
"-minrate", bitrate + "k",
|
||||
"-maxrate", bitrate + "k",
|
||||
"-bufsize", (bitrate * 2) + "k"
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// AV1 AMD encoding
|
||||
/// </summary>
|
||||
/// <param name="bitrate">the bitrate in Kbps</param>
|
||||
/// <returns>the encoding parameters</returns>
|
||||
private static IEnumerable<string> AV1_Amd(int bitrate)
|
||||
{
|
||||
return new[]
|
||||
{
|
||||
"av1_amf",
|
||||
"-b:v:{index}", bitrate + "k",
|
||||
"-minrate", bitrate + "k",
|
||||
"-maxrate", bitrate + "k",
|
||||
"-bufsize", (bitrate * 2) + "k"
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// AV1 NVIDIA encoding
|
||||
/// </summary>
|
||||
/// <param name="bitrate">the bitrate in Kbps</param>
|
||||
/// <returns>the encoding parameters</returns>
|
||||
private static IEnumerable<string> AV1_Nvidia(int bitrate)
|
||||
{
|
||||
return new []
|
||||
{
|
||||
"av1_nvenc",
|
||||
"-b:v:{index}", bitrate + "k",
|
||||
"-minrate", bitrate + "k",
|
||||
"-maxrate", bitrate + "k",
|
||||
"-bufsize", (bitrate * 2) + "k"
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// AV1 QSV encoding
|
||||
/// </summary>
|
||||
/// <param name="bitrate">the bitrate in Kbps</param>
|
||||
/// <returns>the encoding parameters</returns>
|
||||
private static IEnumerable<string> AV1_Qsv(int bitrate)
|
||||
{
|
||||
var args = new List<string>
|
||||
{
|
||||
"av1_qsv",
|
||||
"-b:v:{index}", bitrate + "k",
|
||||
"-minrate", bitrate + "k",
|
||||
"-maxrate", bitrate + "k",
|
||||
"-bufsize", (bitrate * 2) + "k"
|
||||
};
|
||||
if(VaapiHelper.VaapiLinux)
|
||||
args.AddRange(new [] { "-qsv_device", VaapiHelper.VaapiRenderDevice});
|
||||
|
||||
return args.ToArray();
|
||||
}
|
||||
}
|
||||
+319
@@ -0,0 +1,319 @@
|
||||
using System.Runtime.InteropServices;
|
||||
using FileFlows.VideoNodes.FfmpegBuilderNodes.Models;
|
||||
|
||||
namespace FileFlows.VideoNodes.FfmpegBuilderNodes;
|
||||
|
||||
/// <summary>
|
||||
/// Set a video codec encoding by bitrate for a video stream based on users settings
|
||||
/// </summary>
|
||||
public partial class FfmpegBuilderVideoBitrateEncode:VideoEncodeBase
|
||||
{
|
||||
/// <summary>
|
||||
/// The number of outputs for this flow element
|
||||
/// </summary>
|
||||
public override int Outputs => 1;
|
||||
|
||||
/// <summary>
|
||||
/// The Help URL for this flow element
|
||||
/// </summary>
|
||||
public override string HelpUrl => "https://fileflows.com/docs/plugins/video-nodes/ffmpeg-builder/bitrate-encode";
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the codec used to encode
|
||||
/// </summary>
|
||||
[DefaultValue(CODEC_H265)]
|
||||
[Select(nameof(CodecOptions), 1)]
|
||||
public string Codec { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the encoder to use
|
||||
/// </summary>
|
||||
[Select(nameof(Encoders), 2)]
|
||||
[ConditionEquals(nameof(Codec), "/av1/", inverse: true)]
|
||||
public string Encoder { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the bitrate to use in Kbps
|
||||
/// </summary>
|
||||
[NumberInt(3)]
|
||||
[DefaultValue(5_000)]
|
||||
public int Bitrate { get; set; }
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Executes the node
|
||||
/// </summary>
|
||||
/// <param name="args">The node arguments</param>
|
||||
/// <returns>the output return</returns>
|
||||
public override int Execute(NodeParameters args)
|
||||
{
|
||||
var stream = Model.VideoStreams.First(x => x.Deleted == false);
|
||||
|
||||
stream.EncodingParameters.Clear();
|
||||
|
||||
// remove anything that may have been added before
|
||||
stream.Filter = stream.Filter.Where(x => x?.StartsWith("scale_qsv") != true).ToList();
|
||||
|
||||
string encoder = Environment.GetEnvironmentVariable("HW_OFF") == "1" ||
|
||||
(
|
||||
args.Variables?.TryGetValue("HW_OFF", out object oHwOff) == true && (oHwOff as bool? == true || oHwOff?.ToString() == "1")
|
||||
) ? ENCODER_CPU : this.Encoder;
|
||||
|
||||
args.Logger?.ILog("Bitrate: " + Bitrate);
|
||||
args.Logger?.ILog("Codec: " + Codec);
|
||||
if (Codec == CODEC_H264)
|
||||
{
|
||||
var encodingParameters = H264(args, false, encoder, Bitrate).ToArray();
|
||||
args.Logger?.ILog("Encoding Parameters: " +
|
||||
string.Join(" ", encodingParameters.Select(x => x.Contains(" ") ? "\"" + x + "\"" : x)));
|
||||
stream.EncodingParameters.AddRange(encodingParameters);
|
||||
stream.Codec = CODEC_H264;
|
||||
}
|
||||
else if (Codec is CODEC_H265 or CODEC_H265_10BIT or CODEC_H265_8BIT)
|
||||
{
|
||||
bool tenBit = (Codec == CODEC_H265_10BIT || stream.Stream.Is10Bit) && (Codec != CODEC_H265_8BIT);
|
||||
bool forceBitSetting = Codec is CODEC_H265_10BIT or CODEC_H265_8BIT;
|
||||
args.Logger?.ILog("10 Bit: " + tenBit);
|
||||
var encodingParameters = H265(stream, args, tenBit, Bitrate, encoder, stream.Stream.FramesPerSecond, forceBitSetting: forceBitSetting).ToArray();
|
||||
|
||||
|
||||
args.Logger?.ILog("Encoding Parameters: " +
|
||||
string.Join(" ", encodingParameters.Select(x => x.Contains(" ") ? "\"" + x + "\"" : x)));
|
||||
stream.EncodingParameters.AddRange(encodingParameters);
|
||||
stream.Codec = "hevc";
|
||||
}
|
||||
else if (Codec is CODEC_AV1 or CODEC_AV1_10BIT)
|
||||
{
|
||||
bool tenBit = Codec == CODEC_AV1_10BIT || stream.Stream.Is10Bit;
|
||||
args.Logger?.ILog("10 Bit: " + tenBit);
|
||||
var encodingParameters = AV1(args, tenBit, Bitrate, encoder).ToArray();
|
||||
|
||||
args.Logger?.ILog("Encoding Parameters: " +
|
||||
string.Join(" ", encodingParameters.Select(x => x.Contains(" ") ? "\"" + x + "\"" : x)));
|
||||
stream.EncodingParameters.AddRange(encodingParameters);
|
||||
stream.Codec = "av1";
|
||||
}
|
||||
else if (Codec == CODEC_VP9)
|
||||
{
|
||||
var encodingParameters = VP9(args, Bitrate, encoder).ToArray();
|
||||
|
||||
args.Logger?.ILog("Encoding Parameters: " +
|
||||
string.Join(" ", encodingParameters.Select(x => x.Contains(" ") ? "\"" + x + "\"" : x)));
|
||||
stream.EncodingParameters.AddRange(encodingParameters);
|
||||
stream.Codec = "vp9";
|
||||
}
|
||||
else
|
||||
{
|
||||
args.Logger?.ILog("Unknown codec: " + Codec);
|
||||
return 2;
|
||||
}
|
||||
|
||||
stream.ForcedChange = true;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adjust the parameters to use a constant bitrate
|
||||
/// </summary>
|
||||
/// <param name="args">the node parameters</param>
|
||||
/// <param name="parameters">the parameters to alter</param>
|
||||
/// <returns>the adjusted parmaters</returns>
|
||||
private string[] AdjustForBitrate(NodeParameters args, string[] parameters)
|
||||
{
|
||||
var toRemove = new [] { "-rc", "-qp", "-preset", "-spatial-aq", "-g", "-global_quality:v" };
|
||||
int index = Array.FindIndex(parameters, p => toRemove.Contains(p));
|
||||
var modified = new List<string>();
|
||||
for (int i = 0; i < parameters.Length - 1; i++)
|
||||
{
|
||||
if (toRemove.Contains(parameters[i]))
|
||||
{
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
modified.Add(parameters[i]);
|
||||
}
|
||||
modified.Insert(index, "-b:v:{index}");
|
||||
modified.Insert(index + 1, Bitrate + "k");
|
||||
return modified.ToArray();
|
||||
}
|
||||
|
||||
internal static IEnumerable<string> GetEncodingParameters(NodeParameters args, string codec, int bitrate, string encoder, float fps)
|
||||
{
|
||||
if (codec == CODEC_H264)
|
||||
return H264(args, false, encoder, bitrate).Select(x => x.Replace("{index}", "0"));
|
||||
if (codec == CODEC_H265 || codec == CODEC_H265_10BIT)
|
||||
return H265(null, args, codec == CODEC_H265_10BIT, bitrate, encoder, fps).Select(x => x.Replace("{index}", "0"));
|
||||
if(codec == CODEC_AV1)
|
||||
return AV1(args, codec == CODEC_AV1_10BIT, bitrate, encoder).Select(x => x.Replace("{index}", "0"));
|
||||
|
||||
throw new Exception("Unsupported codec: " + codec);
|
||||
}
|
||||
|
||||
private static readonly bool IsMac = RuntimeInformation.IsOSPlatform(OSPlatform.OSX);
|
||||
|
||||
private static IEnumerable<string> H264(NodeParameters args, bool tenBit, string encoder, int bitrate)
|
||||
{
|
||||
List<string> parameters = new List<string>();
|
||||
string[] bit10Filters = null;
|
||||
string[] non10BitFilters = null;
|
||||
if (encoder == ENCODER_CPU)
|
||||
parameters.AddRange(H26x_CPU(false, bitrate, out bit10Filters));
|
||||
else if(IsMac && encoder == ENCODER_MAC)
|
||||
parameters.AddRange(H26x_VideoToolbox(false, bitrate));
|
||||
else if (encoder == ENCODER_NVIDIA)
|
||||
parameters.AddRange(H26x_Nvidia(false, bitrate, out non10BitFilters));
|
||||
else if (encoder == ENCODER_QSV)
|
||||
parameters.AddRange(H26x_Qsv(false, bitrate, 0));
|
||||
else if (encoder == ENCODER_AMF)
|
||||
parameters.AddRange(H26x_Amd(false, bitrate));
|
||||
else if (encoder == ENCODER_VAAPI)
|
||||
parameters.AddRange(H26x_Vaapi(false, bitrate));
|
||||
else if(IsMac && CanUseHardwareEncoding.CanProcess_VideoToolbox_H264(args))
|
||||
parameters.AddRange(H26x_VideoToolbox(false, bitrate));
|
||||
else if (CanUseHardwareEncoding.CanProcess_Nvidia_H264(args))
|
||||
parameters.AddRange(H26x_Nvidia(false,bitrate, out non10BitFilters));
|
||||
else if (CanUseHardwareEncoding.CanProcess_Qsv_H264(args))
|
||||
{
|
||||
parameters.AddRange(H26x_Qsv(false, bitrate, 0));
|
||||
encoder = ENCODER_QSV;
|
||||
}
|
||||
else if (CanUseHardwareEncoding.CanProcess_Amd_H264(args))
|
||||
parameters.AddRange(H26x_Amd(false, bitrate));
|
||||
else if (CanUseHardwareEncoding.CanProcess_Vaapi_H264(args))
|
||||
parameters.AddRange(H26x_Vaapi(false, bitrate));
|
||||
else
|
||||
parameters.AddRange(H26x_CPU(false, bitrate, out bit10Filters));
|
||||
|
||||
if (tenBit)
|
||||
{
|
||||
parameters.AddRange(bit10Filters ?? new string[]
|
||||
{ "-pix_fmt:v:{index}", "p010le", "-profile:v:{index}", "main10" });
|
||||
}
|
||||
|
||||
return parameters;
|
||||
}
|
||||
|
||||
private static IEnumerable<string> H265(FfmpegVideoStream stream, NodeParameters args, bool tenBit, int bitrate,
|
||||
string encoder, float fps, bool forceBitSetting = false)
|
||||
{
|
||||
// hevc_qsv -load_plugin hevc_hw -pix_fmt p010le -profile:v main10 -global_quality 21 -g 24 -look_ahead 1 -look_ahead_depth 60
|
||||
List<string> parameters = new List<string>();
|
||||
string[] bit10Filters = null;
|
||||
string[] non10BitFilters = null;
|
||||
bool qsv = false;
|
||||
if (encoder == ENCODER_CPU)
|
||||
parameters.AddRange(H26x_CPU(true, bitrate, out bit10Filters));
|
||||
else if (IsMac && encoder == ENCODER_MAC)
|
||||
parameters.AddRange(H26x_VideoToolbox(true, bitrate));
|
||||
else if (encoder == ENCODER_NVIDIA)
|
||||
parameters.AddRange(H26x_Nvidia(true, bitrate, out non10BitFilters));
|
||||
else if (encoder == ENCODER_QSV)
|
||||
{
|
||||
parameters.AddRange(H26x_Qsv(true, bitrate, fps));
|
||||
qsv = true;
|
||||
}
|
||||
else if (encoder == ENCODER_AMF)
|
||||
parameters.AddRange(H26x_Amd(true, bitrate));
|
||||
else if (encoder == ENCODER_VAAPI)
|
||||
parameters.AddRange(H26x_Vaapi(true, bitrate));
|
||||
|
||||
else if (IsMac && CanUseHardwareEncoding.CanProcess_VideoToolbox_Hevc(args))
|
||||
parameters.AddRange(H26x_VideoToolbox(true, bitrate));
|
||||
else if (CanUseHardwareEncoding.CanProcess_Nvidia_Hevc(args))
|
||||
parameters.AddRange(H26x_Nvidia(true, bitrate, out non10BitFilters));
|
||||
else if (CanUseHardwareEncoding.CanProcess_Qsv_Hevc(args))
|
||||
{
|
||||
parameters.AddRange(H26x_Qsv(true, bitrate, fps));
|
||||
qsv = true;
|
||||
}
|
||||
else if (CanUseHardwareEncoding.CanProcess_Amd_Hevc(args))
|
||||
parameters.AddRange(H26x_Amd(true, bitrate));
|
||||
else if (CanUseHardwareEncoding.CanProcess_Vaapi_Hevc(args))
|
||||
parameters.AddRange(H26x_Vaapi(true, bitrate));
|
||||
else
|
||||
parameters.AddRange(H26x_CPU(true, bitrate, out bit10Filters));
|
||||
|
||||
if (tenBit)
|
||||
{
|
||||
if (qsv)
|
||||
{
|
||||
parameters.AddRange(new []
|
||||
{
|
||||
"-profile:v:{index}", "main10", "-pix_fmt", "p010le" //, "-vf", "scale_qsv=format=p010le"
|
||||
});
|
||||
// if the stream is passed in, we add it to the filter
|
||||
// if(stream != null)
|
||||
// stream.Filter.Add("scale_qsv=format=p010le");
|
||||
// else // if there is no stream, we specify the -vf directly, this is called by audio to video flow elements
|
||||
// parameters.AddRange(new [] { "-vf", "scale_qsv=format=p010le" });
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
parameters.AddRange(bit10Filters ?? new []
|
||||
{ "-pix_fmt:v:{index}", "p010le", "-profile:v:{index}", "main10" });
|
||||
}
|
||||
}
|
||||
else if(non10BitFilters?.Any() == true)
|
||||
parameters.AddRange(non10BitFilters);
|
||||
else if (forceBitSetting)
|
||||
{
|
||||
parameters.AddRange(new[] { "-pix_fmt:v:{index}", "yuv420p" });
|
||||
}
|
||||
return parameters;
|
||||
}
|
||||
|
||||
|
||||
private static IEnumerable<string> AV1(NodeParameters args, bool tenBit, int bitrate, string encoder)
|
||||
{
|
||||
// hevc_qsv -load_plugin hevc_hw -pix_fmt p010le -profile:v main10 -global_quality 21 -g 24 -look_ahead 1 -look_ahead_depth 60
|
||||
List<string> parameters = new List<string>();
|
||||
|
||||
if (encoder == ENCODER_CPU)
|
||||
parameters.AddRange(AV1_CPU(bitrate));
|
||||
else if(encoder == ENCODER_NVIDIA)
|
||||
parameters.AddRange(AV1_Nvidia(bitrate));
|
||||
else if(encoder == ENCODER_QSV)
|
||||
parameters.AddRange(AV1_Qsv(bitrate));
|
||||
else if(encoder == ENCODER_AMF)
|
||||
parameters.AddRange(AV1_Amd(bitrate));
|
||||
|
||||
else if (CanUseHardwareEncoding.CanProcess_Nvidia_AV1(args))
|
||||
parameters.AddRange(AV1_Nvidia(bitrate));
|
||||
else if (CanUseHardwareEncoding.CanProcess_Qsv_AV1(args))
|
||||
parameters.AddRange(AV1_Qsv(bitrate));
|
||||
else if (CanUseHardwareEncoding.CanProcess_Amd_AV1(args))
|
||||
parameters.AddRange(AV1_Amd(bitrate));
|
||||
else
|
||||
parameters.AddRange(AV1_CPU(bitrate));
|
||||
|
||||
if (tenBit)
|
||||
{
|
||||
bool qsv = parameters.Any(x => x.ToLowerInvariant().Contains("qsv"));
|
||||
bool av1 = parameters.Any(x => x.ToLowerInvariant().Contains("av1"));
|
||||
if(qsv && av1)
|
||||
parameters.AddRange(new[] { "-pix_fmt", "p010le" });
|
||||
else if(qsv)
|
||||
parameters.AddRange(new[] { "-vf", "scale_qsv=format=p010le" });
|
||||
else
|
||||
parameters.AddRange(new[] { "-pix_fmt:v:{index}", "yuv420p10le" });
|
||||
}
|
||||
|
||||
return parameters;
|
||||
}
|
||||
|
||||
private static IEnumerable<string> VP9(NodeParameters args, int bitrate, string encoder)
|
||||
{
|
||||
List<string> parameters = new List<string>();
|
||||
if (encoder == ENCODER_CPU)
|
||||
parameters.AddRange(VP9_CPU(bitrate));
|
||||
else if (encoder == ENCODER_QSV) // if can use hevc they can use vp9
|
||||
parameters.AddRange(VP9_Qsv(bitrate));
|
||||
else if (CanUseHardwareEncoding.CanProcess_Qsv_Hevc(args)) // if can use hevc they can use vp9
|
||||
parameters.AddRange(VP9_Qsv(bitrate));
|
||||
else
|
||||
parameters.AddRange(VP9_CPU(bitrate));
|
||||
return parameters;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
namespace FileFlows.VideoNodes.FfmpegBuilderNodes;
|
||||
|
||||
public partial class FfmpegBuilderVideoBitrateEncode
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets FFmpeg arguments for encoding VP9 using the CPU
|
||||
/// </summary>
|
||||
/// <param name="bitrate">the bitrate in Kbps</param>
|
||||
/// <returns>the FFmpeg arguments</returns>
|
||||
private static IEnumerable<string> VP9_CPU(int bitrate)
|
||||
{
|
||||
return new []
|
||||
{
|
||||
"libvpx-vp9",
|
||||
"-b:v:{index}", bitrate + "k",
|
||||
"-minrate", bitrate + "k",
|
||||
"-maxrate", bitrate + "k",
|
||||
"-bufsize", (bitrate * 2) + "k"
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets FFmpeg arguments for encoding VP9 using the Intel's QSV hardware encoder
|
||||
/// </summary>
|
||||
/// <param name="bitrate">the bitrate in Kbps</param>
|
||||
/// <returns>the FFmpeg arguments</returns>
|
||||
private static IEnumerable<string> VP9_Qsv(int bitrate)
|
||||
{
|
||||
var parameters = new List<string>();
|
||||
parameters.AddRange(new[]
|
||||
{
|
||||
"vp9_qsv",
|
||||
"-b:v:{index}", bitrate + "k",
|
||||
"-minrate", bitrate + "k",
|
||||
"-maxrate", bitrate + "k",
|
||||
"-bufsize", (bitrate * 2) + "k"
|
||||
});
|
||||
return parameters;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
using System.Globalization;
|
||||
|
||||
namespace FileFlows.VideoNodes.FfmpegBuilderNodes;
|
||||
|
||||
public partial class FfmpegBuilderVideoBitrateEncode
|
||||
{
|
||||
|
||||
private static IEnumerable<string> H26x_CPU(bool h265, int bitrate, out string[] bit10Filters)
|
||||
{
|
||||
bit10Filters = new[]
|
||||
{
|
||||
"-pix_fmt:v:{index}", "yuv420p10le", "-profile:v:{index}", "main10"
|
||||
};
|
||||
return new []
|
||||
{
|
||||
h265 ? "libx265" : "libx264",
|
||||
"-b:v:{index}", bitrate + "k",
|
||||
"-minrate", bitrate + "k",
|
||||
"-maxrate", bitrate + "k",
|
||||
"-bufsize", (bitrate * 2) + "k"
|
||||
};
|
||||
}
|
||||
|
||||
private static IEnumerable<string> H26x_Nvidia(bool h265, int bitrate, out string[] non10BitFilters)
|
||||
{
|
||||
if (h265 == false)
|
||||
non10BitFilters = new[] { "-pix_fmt:v:{index}", "yuv420p" };
|
||||
else
|
||||
non10BitFilters = null;
|
||||
|
||||
return new []
|
||||
{
|
||||
h265 ? "hevc_nvenc" : "h264_nvenc",
|
||||
"-b:v:{index}", bitrate + "k",
|
||||
"-minrate", bitrate + "k",
|
||||
"-maxrate", bitrate + "k",
|
||||
"-bufsize", (bitrate * 2) + "k"
|
||||
};
|
||||
}
|
||||
|
||||
private static IEnumerable<string> H26x_Qsv(bool h265, int bitrate, float fps)
|
||||
{
|
||||
//hevc_qsv -load_plugin hevc_hw -pix_fmt p010le -profile:v main10 -global_quality 21 -g 24 -look_ahead 1 -look_ahead_depth 60
|
||||
var parameters = new List<string>();
|
||||
if (h265)
|
||||
{
|
||||
parameters.AddRange(new[]
|
||||
{
|
||||
"hevc_qsv",
|
||||
"-load_plugin", "hevc_hw",
|
||||
"-g", (fps < 1 ? 29.97 : fps).ToString(CultureInfo.InvariantCulture)
|
||||
});
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
parameters.AddRange(new[]
|
||||
{
|
||||
"h264_qsv"
|
||||
});
|
||||
|
||||
}
|
||||
parameters.AddRange(new[]
|
||||
{
|
||||
"-b:v:{index}", bitrate + "k",
|
||||
"-minrate", bitrate + "k",
|
||||
"-maxrate", bitrate + "k",
|
||||
"-bufsize", (bitrate * 2) + "k"
|
||||
});
|
||||
return parameters;
|
||||
}
|
||||
|
||||
private static IEnumerable<string> H26x_Amd(bool h265, int bitrate)
|
||||
{
|
||||
return new[]
|
||||
{
|
||||
h265 ? "hevc_amf" : "h264_amf",
|
||||
"-b:v:{index}", bitrate + "k",
|
||||
"-minrate", bitrate + "k",
|
||||
"-maxrate", bitrate + "k",
|
||||
"-bufsize", (bitrate * 2) + "k"
|
||||
};
|
||||
}
|
||||
private static IEnumerable<string> H26x_Vaapi(bool h265, int bitrate)
|
||||
{
|
||||
return new[]
|
||||
{
|
||||
h265 ? "hevc_vaapi" : "h264_vaapi",
|
||||
"-b:v:{index}", bitrate + "k",
|
||||
"-minrate", bitrate + "k",
|
||||
"-maxrate", bitrate + "k",
|
||||
"-bufsize", (bitrate * 2) + "k"
|
||||
};
|
||||
}
|
||||
private static IEnumerable<string> H26x_VideoToolbox(bool h265, int bitrate)
|
||||
{
|
||||
return new[]
|
||||
{
|
||||
h265 ? "hevc_videotoolbox" : "h264_videotoolbox",
|
||||
"-b:v:{index}", bitrate + "k",
|
||||
"-minrate", bitrate + "k",
|
||||
"-maxrate", bitrate + "k",
|
||||
"-bufsize", (bitrate * 2) + "k"
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -25,7 +25,7 @@ public class FfmpegBuilderVideoBitrate : FfmpegBuilderNode
|
||||
}
|
||||
if(Bitrate < 0)
|
||||
{
|
||||
args.Logger?.ELog("Minimum birate not set");
|
||||
args.Logger?.ELog("Minimum bitrate not set");
|
||||
return -1;
|
||||
}
|
||||
float currentBitrate = (int)(video.Stream.Bitrate / 1000f);
|
||||
|
||||
+1
-68
@@ -6,27 +6,13 @@ namespace FileFlows.VideoNodes.FfmpegBuilderNodes;
|
||||
/// <summary>
|
||||
/// Set a video codec encoding for a video stream based on users settings
|
||||
/// </summary>
|
||||
public partial class FfmpegBuilderVideoEncode:FfmpegBuilderNode
|
||||
public partial class FfmpegBuilderVideoEncode:VideoEncodeBase
|
||||
{
|
||||
/// <summary>
|
||||
/// The number of outputs for this flow element
|
||||
/// </summary>
|
||||
public override int Outputs => 1;
|
||||
|
||||
internal const string CODEC_H264 = "h264";
|
||||
internal const string CODEC_H265 = "h265";
|
||||
internal const string CODEC_H265_8BIT = "h265 8BIT";
|
||||
internal const string CODEC_H265_10BIT = "h265 10BIT";
|
||||
internal const string CODEC_AV1 = "av1";
|
||||
internal const string CODEC_AV1_10BIT = "av1 10BIT";
|
||||
internal const string CODEC_VP9 = "vp9";
|
||||
|
||||
internal const string ENCODER_CPU = "CPU";
|
||||
internal const string ENCODER_NVIDIA = "NVIDIA";
|
||||
internal const string ENCODER_QSV = "Intel QSV";
|
||||
internal const string ENCODER_VAAPI = "VAAPI";
|
||||
internal const string ENCODER_AMF = "AMD AMF";
|
||||
internal const string ENCODER_MAC = "Mac Video Toolbox";
|
||||
|
||||
/// <summary>
|
||||
/// The Help URL for this flow element
|
||||
@@ -45,65 +31,12 @@ public partial class FfmpegBuilderVideoEncode:FfmpegBuilderNode
|
||||
[ChangeValue(nameof(Quality), 28, CODEC_VP9)]
|
||||
[Select(nameof(CodecOptions), 1)]
|
||||
public string Codec { get; set; }
|
||||
|
||||
private static List<ListOption> _CodecOptions;
|
||||
/// <summary>
|
||||
/// Gets or sets the codec options
|
||||
/// </summary>
|
||||
public static List<ListOption> CodecOptions
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_CodecOptions == null)
|
||||
{
|
||||
_CodecOptions = new List<ListOption>
|
||||
{
|
||||
new () { Label = "H.264", Value = CODEC_H264 },
|
||||
// new () { Label = "H.264 (10-Bit)", Value = CODEC_H264_10BIT },
|
||||
new () { Label = "HEVC (Automatic)", Value = CODEC_H265 },
|
||||
new () { Label = "HEVC (8-Bit)", Value = CODEC_H265_8BIT },
|
||||
new () { Label = "HEVC (10-Bit)", Value = CODEC_H265_10BIT },
|
||||
new () { Label = "AV1", Value = CODEC_AV1 },
|
||||
new () { Label = "AV1 (10-Bit)", Value = CODEC_AV1_10BIT },
|
||||
new () { Label = "VP9", Value = CODEC_VP9 },
|
||||
};
|
||||
}
|
||||
return _CodecOptions;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the encoder to use
|
||||
/// </summary>
|
||||
[Select(nameof(Encoders), 2)]
|
||||
[ConditionEquals(nameof(Codec), "/av1/", inverse: true)]
|
||||
public string Encoder { get; set; }
|
||||
|
||||
private static List<ListOption> _Encoders;
|
||||
/// <summary>
|
||||
/// Gets or sets the encoders options
|
||||
/// </summary>
|
||||
public static List<ListOption> Encoders
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_Encoders == null)
|
||||
{
|
||||
_Encoders = new List<ListOption>
|
||||
{
|
||||
new () { Label = "Automatic", Value = "" },
|
||||
new () { Label = "CPU", Value = "CPU" },
|
||||
new () { Label = "NVIDIA", Value = "NVIDIA" },
|
||||
new () { Label = "Intel QSV", Value = "Intel QSV" },
|
||||
new () { Label = "VAAPI", Value = "VAAPI" },
|
||||
new () { Label = "AMD AMF", Value = "AMD AMF" },
|
||||
new () { Label = "Mac Video Toolbox", Value = "Mac Video Toolbox" },
|
||||
};
|
||||
}
|
||||
return _Encoders;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the quality of the video encode
|
||||
/// </summary>
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
namespace FileFlows.VideoNodes.FfmpegBuilderNodes;
|
||||
|
||||
/// <summary>
|
||||
/// Base for the common Video Encode flow elements
|
||||
/// </summary>
|
||||
public abstract class VideoEncodeBase : FfmpegBuilderNode
|
||||
{
|
||||
|
||||
internal const string CODEC_H264 = "h264";
|
||||
internal const string CODEC_H265 = "h265";
|
||||
internal const string CODEC_H265_8BIT = "h265 8BIT";
|
||||
internal const string CODEC_H265_10BIT = "h265 10BIT";
|
||||
internal const string CODEC_AV1 = "av1";
|
||||
internal const string CODEC_AV1_10BIT = "av1 10BIT";
|
||||
internal const string CODEC_VP9 = "vp9";
|
||||
|
||||
internal const string ENCODER_CPU = "CPU";
|
||||
internal const string ENCODER_NVIDIA = "NVIDIA";
|
||||
internal const string ENCODER_QSV = "Intel QSV";
|
||||
internal const string ENCODER_VAAPI = "VAAPI";
|
||||
internal const string ENCODER_AMF = "AMD AMF";
|
||||
internal const string ENCODER_MAC = "Mac Video Toolbox";
|
||||
|
||||
|
||||
|
||||
private static List<ListOption> _CodecOptions;
|
||||
/// <summary>
|
||||
/// Gets or sets the codec options
|
||||
/// </summary>
|
||||
public static List<ListOption> CodecOptions
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_CodecOptions == null)
|
||||
{
|
||||
_CodecOptions = new List<ListOption>
|
||||
{
|
||||
new () { Label = "H.264", Value = CODEC_H264 },
|
||||
// new () { Label = "H.264 (10-Bit)", Value = CODEC_H264_10BIT },
|
||||
new () { Label = "HEVC (Automatic)", Value = CODEC_H265 },
|
||||
new () { Label = "HEVC (8-Bit)", Value = CODEC_H265_8BIT },
|
||||
new () { Label = "HEVC (10-Bit)", Value = CODEC_H265_10BIT },
|
||||
new () { Label = "AV1", Value = CODEC_AV1 },
|
||||
new () { Label = "AV1 (10-Bit)", Value = CODEC_AV1_10BIT },
|
||||
new () { Label = "VP9", Value = CODEC_VP9 },
|
||||
};
|
||||
}
|
||||
return _CodecOptions;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static List<ListOption> _Encoders;
|
||||
/// <summary>
|
||||
/// Gets or sets the encoders options
|
||||
/// </summary>
|
||||
public static List<ListOption> Encoders
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_Encoders == null)
|
||||
{
|
||||
_Encoders = new List<ListOption>
|
||||
{
|
||||
new () { Label = "Automatic", Value = "" },
|
||||
new () { Label = "CPU", Value = "CPU" },
|
||||
new () { Label = "NVIDIA", Value = "NVIDIA" },
|
||||
new () { Label = "Intel QSV", Value = "Intel QSV" },
|
||||
new () { Label = "VAAPI", Value = "VAAPI" },
|
||||
new () { Label = "AMD AMF", Value = "AMD AMF" },
|
||||
new () { Label = "Mac Video Toolbox", Value = "Mac Video Toolbox" },
|
||||
};
|
||||
}
|
||||
return _Encoders;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -703,6 +703,22 @@
|
||||
"Quality-Suffix": "(Higher Quality, larger file)"
|
||||
}
|
||||
},
|
||||
"FfmpegBuilderVideoBitrateEncode": {
|
||||
"Label": "FFMPEG Builder: Bitrate Encode",
|
||||
"Description": "Sets the FFMPEG Builder to encode the video with simple to use presets based on Bitrate",
|
||||
"Outputs": {
|
||||
"1": "FFMPEG Builder video streams set to encode"
|
||||
},
|
||||
"Fields": {
|
||||
"Codec": "Codec",
|
||||
"Bitrate": "Bitrate",
|
||||
"Bitrate-Suffix": "Kbps",
|
||||
"Encoder": "Encoder",
|
||||
"Encoder-Help": "The encoder to force to use. If you specify a hardware encoder that is unavailable, the encode will fail.",
|
||||
"HardwareEncoding": "Hardware Encode",
|
||||
"HardwareEncoding-Help": "When checked, will test to see if hardware encoders are found on the Processing Node, and if found will use hardware encoding, otherwise will fallback to CPU encoding."
|
||||
}
|
||||
},
|
||||
"FfmpegBuilderVideoTag": {
|
||||
"Label": "FFMPEG Builder: Video Tag",
|
||||
"Description": "Sets a video tag on the file",
|
||||
|
||||
Reference in New Issue
Block a user