Add AV1 hardware and software encoding

Signed-off-by: nyanmisaka <nst799610810@gmail.com>
pull/9907/head
nyanmisaka 2 years ago
parent 0df6fd9cf2
commit be01aeecd9

@ -46,6 +46,7 @@ namespace MediaBrowser.Controller.MediaEncoding
private readonly Version _minFFmpegImplictHwaccel = new Version(6, 0); private readonly Version _minFFmpegImplictHwaccel = new Version(6, 0);
private readonly Version _minFFmpegHwaUnsafeOutput = new Version(6, 0); private readonly Version _minFFmpegHwaUnsafeOutput = new Version(6, 0);
private readonly Version _minFFmpegOclCuTonemapMode = new Version(5, 1, 3); private readonly Version _minFFmpegOclCuTonemapMode = new Version(5, 1, 3);
private readonly Version _minFFmpegSvtAv1Params = new Version(5, 1);
private static readonly string[] _videoProfilesH264 = new[] private static readonly string[] _videoProfilesH264 = new[]
{ {
@ -65,6 +66,13 @@ namespace MediaBrowser.Controller.MediaEncoding
"Main10" "Main10"
}; };
private static readonly string[] _videoProfilesAv1 = new[]
{
"Main",
"High",
"Professional",
};
private static readonly HashSet<string> _mp4ContainerNames = new(StringComparer.OrdinalIgnoreCase) private static readonly HashSet<string> _mp4ContainerNames = new(StringComparer.OrdinalIgnoreCase)
{ {
"mp4", "mp4",
@ -113,12 +121,15 @@ namespace MediaBrowser.Controller.MediaEncoding
} }
public string GetH264Encoder(EncodingJobInfo state, EncodingOptions encodingOptions) public string GetH264Encoder(EncodingJobInfo state, EncodingOptions encodingOptions)
=> GetH264OrH265Encoder("libx264", "h264", state, encodingOptions); => GetH26xOrAv1Encoder("libx264", "h264", state, encodingOptions);
public string GetH265Encoder(EncodingJobInfo state, EncodingOptions encodingOptions) public string GetH265Encoder(EncodingJobInfo state, EncodingOptions encodingOptions)
=> GetH264OrH265Encoder("libx265", "hevc", state, encodingOptions); => GetH26xOrAv1Encoder("libx265", "hevc", state, encodingOptions);
public string GetAv1Encoder(EncodingJobInfo state, EncodingOptions encodingOptions)
=> GetH26xOrAv1Encoder("libsvtav1", "av1", state, encodingOptions);
private string GetH264OrH265Encoder(string defaultEncoder, string hwEncoder, EncodingJobInfo state, EncodingOptions encodingOptions) private string GetH26xOrAv1Encoder(string defaultEncoder, string hwEncoder, EncodingJobInfo state, EncodingOptions encodingOptions)
{ {
// Only use alternative encoders for video files. // Only use alternative encoders for video files.
// When using concat with folder rips, if the mfx session fails to initialize, ffmpeg will be stuck retrying and will not exit gracefully // When using concat with folder rips, if the mfx session fails to initialize, ffmpeg will be stuck retrying and will not exit gracefully
@ -266,6 +277,11 @@ namespace MediaBrowser.Controller.MediaEncoding
if (!string.IsNullOrEmpty(codec)) if (!string.IsNullOrEmpty(codec))
{ {
if (string.Equals(codec, "av1", StringComparison.OrdinalIgnoreCase))
{
return GetAv1Encoder(state, encodingOptions);
}
if (string.Equals(codec, "h265", StringComparison.OrdinalIgnoreCase) if (string.Equals(codec, "h265", StringComparison.OrdinalIgnoreCase)
|| string.Equals(codec, "hevc", StringComparison.OrdinalIgnoreCase)) || string.Equals(codec, "hevc", StringComparison.OrdinalIgnoreCase))
{ {
@ -565,6 +581,11 @@ namespace MediaBrowser.Controller.MediaEncoding
return Array.FindIndex(_videoProfilesH265, x => string.Equals(x, profile, StringComparison.OrdinalIgnoreCase)); return Array.FindIndex(_videoProfilesH265, x => string.Equals(x, profile, StringComparison.OrdinalIgnoreCase));
} }
if (string.Equals("av1", videoCodec, StringComparison.OrdinalIgnoreCase))
{
return Array.FindIndex(_videoProfilesAv1, x => string.Equals(x, profile, StringComparison.OrdinalIgnoreCase));
}
return -1; return -1;
} }
@ -1204,6 +1225,11 @@ namespace MediaBrowser.Controller.MediaEncoding
return FormattableString.Invariant($" -b:v {bitrate}"); return FormattableString.Invariant($" -b:v {bitrate}");
} }
if (string.Equals(videoCodec, "libsvtav1", StringComparison.OrdinalIgnoreCase))
{
return FormattableString.Invariant($" -b:v {bitrate} -bufsize {bufsize}");
}
if (string.Equals(videoCodec, "libx264", StringComparison.OrdinalIgnoreCase) if (string.Equals(videoCodec, "libx264", StringComparison.OrdinalIgnoreCase)
|| string.Equals(videoCodec, "libx265", StringComparison.OrdinalIgnoreCase)) || string.Equals(videoCodec, "libx265", StringComparison.OrdinalIgnoreCase))
{ {
@ -1211,14 +1237,16 @@ namespace MediaBrowser.Controller.MediaEncoding
} }
if (string.Equals(videoCodec, "h264_amf", StringComparison.OrdinalIgnoreCase) if (string.Equals(videoCodec, "h264_amf", StringComparison.OrdinalIgnoreCase)
|| string.Equals(videoCodec, "hevc_amf", StringComparison.OrdinalIgnoreCase)) || string.Equals(videoCodec, "hevc_amf", StringComparison.OrdinalIgnoreCase)
|| string.Equals(videoCodec, "av1_amf", StringComparison.OrdinalIgnoreCase))
{ {
// Override the too high default qmin 18 in transcoding preset // Override the too high default qmin 18 in transcoding preset
return FormattableString.Invariant($" -rc cbr -qmin 0 -qmax 32 -b:v {bitrate} -maxrate {bitrate} -bufsize {bufsize}"); return FormattableString.Invariant($" -rc cbr -qmin 0 -qmax 32 -b:v {bitrate} -maxrate {bitrate} -bufsize {bufsize}");
} }
if (string.Equals(videoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase) if (string.Equals(videoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase)
|| string.Equals(videoCodec, "hevc_vaapi", StringComparison.OrdinalIgnoreCase)) || string.Equals(videoCodec, "hevc_vaapi", StringComparison.OrdinalIgnoreCase)
|| string.Equals(videoCodec, "av1_vaapi", StringComparison.OrdinalIgnoreCase))
{ {
// VBR in i965 driver may result in pixelated output. // VBR in i965 driver may result in pixelated output.
if (_mediaEncoder.IsVaapiDeviceInteli965) if (_mediaEncoder.IsVaapiDeviceInteli965)
@ -1236,14 +1264,23 @@ namespace MediaBrowser.Controller.MediaEncoding
{ {
if (double.TryParse(level, CultureInfo.InvariantCulture, out double requestLevel)) if (double.TryParse(level, CultureInfo.InvariantCulture, out double requestLevel))
{ {
if (string.Equals(state.ActualOutputVideoCodec, "hevc", StringComparison.OrdinalIgnoreCase) if (string.Equals(state.ActualOutputVideoCodec, "av1", StringComparison.OrdinalIgnoreCase))
|| string.Equals(state.ActualOutputVideoCodec, "h265", StringComparison.OrdinalIgnoreCase)) {
// Transcode to level 5.3 (15) and lower for maximum compatibility.
// https://en.wikipedia.org/wiki/AV1#Levels
if (requestLevel < 0 || requestLevel >= 15)
{
return "15";
}
}
else if (string.Equals(state.ActualOutputVideoCodec, "hevc", StringComparison.OrdinalIgnoreCase)
|| string.Equals(state.ActualOutputVideoCodec, "h265", StringComparison.OrdinalIgnoreCase))
{ {
// Transcode to level 5.0 and lower for maximum compatibility. // Transcode to level 5.0 and lower for maximum compatibility.
// Level 5.0 is suitable for up to 4k 30fps hevc encoding, otherwise let the encoder to handle it. // Level 5.0 is suitable for up to 4k 30fps hevc encoding, otherwise let the encoder to handle it.
// https://en.wikipedia.org/wiki/High_Efficiency_Video_Coding_tiers_and_levels // https://en.wikipedia.org/wiki/High_Efficiency_Video_Coding_tiers_and_levels
// MaxLumaSampleRate = 3840*2160*30 = 248832000 < 267386880. // MaxLumaSampleRate = 3840*2160*30 = 248832000 < 267386880.
if (requestLevel >= 150) if (requestLevel < 0 || requestLevel >= 150)
{ {
return "150"; return "150";
} }
@ -1253,7 +1290,7 @@ namespace MediaBrowser.Controller.MediaEncoding
// Transcode to level 5.1 and lower for maximum compatibility. // Transcode to level 5.1 and lower for maximum compatibility.
// h264 4k 30fps requires at least level 5.1 otherwise it will break on safari fmp4. // h264 4k 30fps requires at least level 5.1 otherwise it will break on safari fmp4.
// https://en.wikipedia.org/wiki/Advanced_Video_Coding#Levels // https://en.wikipedia.org/wiki/Advanced_Video_Coding#Levels
if (requestLevel >= 51) if (requestLevel < 0 || requestLevel >= 51)
{ {
return "51"; return "51";
} }
@ -1391,14 +1428,18 @@ namespace MediaBrowser.Controller.MediaEncoding
|| string.Equals(codec, "h264_amf", StringComparison.OrdinalIgnoreCase) || string.Equals(codec, "h264_amf", StringComparison.OrdinalIgnoreCase)
|| string.Equals(codec, "hevc_qsv", StringComparison.OrdinalIgnoreCase) || string.Equals(codec, "hevc_qsv", StringComparison.OrdinalIgnoreCase)
|| string.Equals(codec, "hevc_nvenc", StringComparison.OrdinalIgnoreCase) || string.Equals(codec, "hevc_nvenc", StringComparison.OrdinalIgnoreCase)
|| string.Equals(codec, "hevc_amf", StringComparison.OrdinalIgnoreCase)) || string.Equals(codec, "av1_qsv", StringComparison.OrdinalIgnoreCase)
|| string.Equals(codec, "av1_nvenc", StringComparison.OrdinalIgnoreCase)
|| string.Equals(codec, "av1_amf", StringComparison.OrdinalIgnoreCase)
|| string.Equals(codec, "libsvtav1", StringComparison.OrdinalIgnoreCase))
{ {
args += gopArg; args += gopArg;
} }
else if (string.Equals(codec, "libx264", StringComparison.OrdinalIgnoreCase) else if (string.Equals(codec, "libx264", StringComparison.OrdinalIgnoreCase)
|| string.Equals(codec, "libx265", StringComparison.OrdinalIgnoreCase) || string.Equals(codec, "libx265", StringComparison.OrdinalIgnoreCase)
|| string.Equals(codec, "h264_vaapi", StringComparison.OrdinalIgnoreCase) || string.Equals(codec, "h264_vaapi", StringComparison.OrdinalIgnoreCase)
|| string.Equals(codec, "hevc_vaapi", StringComparison.OrdinalIgnoreCase)) || string.Equals(codec, "hevc_vaapi", StringComparison.OrdinalIgnoreCase)
|| string.Equals(codec, "av1_vaapi", StringComparison.OrdinalIgnoreCase))
{ {
args += keyFrameArg; args += keyFrameArg;
@ -1534,18 +1575,60 @@ namespace MediaBrowser.Controller.MediaEncoding
param += " -crf " + defaultCrf; param += " -crf " + defaultCrf;
} }
} }
else if (string.Equals(videoEncoder, "libsvtav1", StringComparison.OrdinalIgnoreCase))
{
// Default to use the recommended preset 10.
// Omit presets < 5, which are too slow for on the fly encoding.
// https://gitlab.com/AOMediaCodec/SVT-AV1/-/blob/master/Docs/Ffmpeg.md
param += encodingOptions.EncoderPreset switch
{
"veryslow" => " -preset 5",
"slower" => " -preset 6",
"slow" => " -preset 7",
"medium" => " -preset 8",
"fast" => " -preset 9",
"faster" => " -preset 10",
"veryfast" => " -preset 11",
"superfast" => " -preset 12",
"ultrafast" => " -preset 13",
_ => " -preset 10"
};
}
else if (string.Equals(videoEncoder, "h264_vaapi", StringComparison.OrdinalIgnoreCase)
|| string.Equals(videoEncoder, "hevc_vaapi", StringComparison.OrdinalIgnoreCase)
|| string.Equals(videoEncoder, "av1_vaapi", StringComparison.OrdinalIgnoreCase))
{
// -compression_level is not reliable on AMD.
if (_mediaEncoder.IsVaapiDeviceInteliHD)
{
param += encodingOptions.EncoderPreset switch
{
"veryslow" => " -compression_level 1",
"slower" => " -compression_level 2",
"slow" => " -compression_level 3",
"medium" => " -compression_level 4",
"fast" => " -compression_level 5",
"faster" => " -compression_level 6",
"veryfast" => " -compression_level 7",
"superfast" => " -compression_level 7",
"ultrafast" => " -compression_level 7",
_ => string.Empty
};
}
}
else if (string.Equals(videoEncoder, "h264_qsv", StringComparison.OrdinalIgnoreCase) // h264 (h264_qsv) else if (string.Equals(videoEncoder, "h264_qsv", StringComparison.OrdinalIgnoreCase) // h264 (h264_qsv)
|| string.Equals(videoEncoder, "hevc_qsv", StringComparison.OrdinalIgnoreCase)) // hevc (hevc_qsv) || string.Equals(videoEncoder, "hevc_qsv", StringComparison.OrdinalIgnoreCase) // hevc (hevc_qsv)
|| string.Equals(videoEncoder, "av1_qsv", StringComparison.OrdinalIgnoreCase)) // av1 (av1_qsv)
{ {
string[] valid_h264_qsv = { "veryslow", "slower", "slow", "medium", "fast", "faster", "veryfast" }; string[] valid_presets = { "veryslow", "slower", "slow", "medium", "fast", "faster", "veryfast" };
if (valid_h264_qsv.Contains(encodingOptions.EncoderPreset, StringComparison.OrdinalIgnoreCase)) if (valid_presets.Contains(encodingOptions.EncoderPreset, StringComparison.OrdinalIgnoreCase))
{ {
param += " -preset " + encodingOptions.EncoderPreset; param += " -preset " + encodingOptions.EncoderPreset;
} }
else else
{ {
param += " -preset 7"; param += " -preset veryfast";
} }
// Only h264_qsv has look_ahead option // Only h264_qsv has look_ahead option
@ -1555,7 +1638,8 @@ namespace MediaBrowser.Controller.MediaEncoding
} }
} }
else if (string.Equals(videoEncoder, "h264_nvenc", StringComparison.OrdinalIgnoreCase) // h264 (h264_nvenc) else if (string.Equals(videoEncoder, "h264_nvenc", StringComparison.OrdinalIgnoreCase) // h264 (h264_nvenc)
|| string.Equals(videoEncoder, "hevc_nvenc", StringComparison.OrdinalIgnoreCase)) // hevc (hevc_nvenc) || string.Equals(videoEncoder, "hevc_nvenc", StringComparison.OrdinalIgnoreCase) // hevc (hevc_nvenc)
|| string.Equals(videoEncoder, "av1_nvenc", StringComparison.OrdinalIgnoreCase)) // av1 (av1_nvenc)
{ {
switch (encodingOptions.EncoderPreset) switch (encodingOptions.EncoderPreset)
{ {
@ -1595,7 +1679,8 @@ namespace MediaBrowser.Controller.MediaEncoding
} }
} }
else if (string.Equals(videoEncoder, "h264_amf", StringComparison.OrdinalIgnoreCase) // h264 (h264_amf) else if (string.Equals(videoEncoder, "h264_amf", StringComparison.OrdinalIgnoreCase) // h264 (h264_amf)
|| string.Equals(videoEncoder, "hevc_amf", StringComparison.OrdinalIgnoreCase)) // hevc (hevc_amf) || string.Equals(videoEncoder, "hevc_amf", StringComparison.OrdinalIgnoreCase) // hevc (hevc_amf)
|| string.Equals(videoEncoder, "av1_amf", StringComparison.OrdinalIgnoreCase)) // av1 (av1_amf)
{ {
switch (encodingOptions.EncoderPreset) switch (encodingOptions.EncoderPreset)
{ {
@ -1622,9 +1707,15 @@ namespace MediaBrowser.Controller.MediaEncoding
break; break;
} }
if (string.Equals(videoEncoder, "hevc_amf", StringComparison.OrdinalIgnoreCase)
|| string.Equals(videoEncoder, "av1_amf", StringComparison.OrdinalIgnoreCase))
{
param += " -header_insertion_mode gop";
}
if (string.Equals(videoEncoder, "hevc_amf", StringComparison.OrdinalIgnoreCase)) if (string.Equals(videoEncoder, "hevc_amf", StringComparison.OrdinalIgnoreCase))
{ {
param += " -header_insertion_mode gop -gops_per_idr 1"; param += " -gops_per_idr 1";
} }
} }
else if (string.Equals(videoEncoder, "libvpx", StringComparison.OrdinalIgnoreCase)) // vp8 else if (string.Equals(videoEncoder, "libvpx", StringComparison.OrdinalIgnoreCase)) // vp8
@ -1755,6 +1846,14 @@ namespace MediaBrowser.Controller.MediaEncoding
profile = "high"; profile = "high";
} }
// We only need Main profile of AV1 encoders.
if (videoEncoder.Contains("av1", StringComparison.OrdinalIgnoreCase)
&& (profile.Contains("high", StringComparison.OrdinalIgnoreCase)
|| profile.Contains("professional", StringComparison.OrdinalIgnoreCase)))
{
profile = "main";
}
// h264_vaapi does not support Baseline profile, force Constrained Baseline in this case, // h264_vaapi does not support Baseline profile, force Constrained Baseline in this case,
// which is compatible (and ugly). // which is compatible (and ugly).
if (string.Equals(videoEncoder, "h264_vaapi", StringComparison.OrdinalIgnoreCase) if (string.Equals(videoEncoder, "h264_vaapi", StringComparison.OrdinalIgnoreCase)
@ -1822,19 +1921,41 @@ namespace MediaBrowser.Controller.MediaEncoding
param += " -level " + (hevcLevel / 3); param += " -level " + (hevcLevel / 3);
} }
} }
else if (string.Equals(videoEncoder, "av1_qsv", StringComparison.OrdinalIgnoreCase)
|| string.Equals(videoEncoder, "libsvtav1", StringComparison.OrdinalIgnoreCase))
{
// libsvtav1 and av1_qsv use -level 60 instead of -level 16
// https://aomedia.org/av1/specification/annex-a/
if (int.TryParse(level, NumberStyles.Any, CultureInfo.InvariantCulture, out int av1Level))
{
var x = 2 + (av1Level >> 2);
var y = av1Level & 3;
var res = (x * 10) + y;
param += " -level " + res;
}
}
else if (string.Equals(videoEncoder, "h264_amf", StringComparison.OrdinalIgnoreCase) else if (string.Equals(videoEncoder, "h264_amf", StringComparison.OrdinalIgnoreCase)
|| string.Equals(videoEncoder, "hevc_amf", StringComparison.OrdinalIgnoreCase)) || string.Equals(videoEncoder, "hevc_amf", StringComparison.OrdinalIgnoreCase)
|| string.Equals(videoEncoder, "av1_amf", StringComparison.OrdinalIgnoreCase))
{ {
param += " -level " + level; param += " -level " + level;
} }
else if (string.Equals(videoEncoder, "h264_nvenc", StringComparison.OrdinalIgnoreCase) else if (string.Equals(videoEncoder, "h264_nvenc", StringComparison.OrdinalIgnoreCase)
|| string.Equals(videoEncoder, "hevc_nvenc", StringComparison.OrdinalIgnoreCase) || string.Equals(videoEncoder, "hevc_nvenc", StringComparison.OrdinalIgnoreCase)
|| string.Equals(videoEncoder, "h264_vaapi", StringComparison.OrdinalIgnoreCase) || string.Equals(videoEncoder, "av1_nvenc", StringComparison.OrdinalIgnoreCase))
|| string.Equals(videoEncoder, "hevc_vaapi", StringComparison.OrdinalIgnoreCase))
{ {
// level option may cause NVENC to fail. // level option may cause NVENC to fail.
// NVENC cannot adjust the given level, just throw an error. // NVENC cannot adjust the given level, just throw an error.
}
else if (string.Equals(videoEncoder, "h264_vaapi", StringComparison.OrdinalIgnoreCase)
|| string.Equals(videoEncoder, "hevc_vaapi", StringComparison.OrdinalIgnoreCase)
|| string.Equals(videoEncoder, "av1_vaapi", StringComparison.OrdinalIgnoreCase))
{
// level option may cause corrupted frames on AMD VAAPI. // level option may cause corrupted frames on AMD VAAPI.
if (_mediaEncoder.IsVaapiDeviceInteliHD || _mediaEncoder.IsVaapiDeviceInteli965)
{
param += " -level " + level;
}
} }
else if (!string.Equals(videoEncoder, "libx265", StringComparison.OrdinalIgnoreCase)) else if (!string.Equals(videoEncoder, "libx265", StringComparison.OrdinalIgnoreCase))
{ {
@ -1856,6 +1977,12 @@ namespace MediaBrowser.Controller.MediaEncoding
param += " -x265-params:0 no-info=1"; param += " -x265-params:0 no-info=1";
} }
if (string.Equals(videoEncoder, "libsvtav1", StringComparison.OrdinalIgnoreCase)
&& _mediaEncoder.EncoderVersion >= _minFFmpegSvtAv1Params)
{
param += " -svtav1-params:0 rc=1:tune=0:film-grain=0:enable-overlays=1:enable-tf=0";
}
return param; return param;
} }
@ -5810,19 +5937,25 @@ namespace MediaBrowser.Controller.MediaEncoding
private void ShiftVideoCodecsIfNeeded(List<string> videoCodecs, EncodingOptions encodingOptions) private void ShiftVideoCodecsIfNeeded(List<string> videoCodecs, EncodingOptions encodingOptions)
{ {
// Shift hevc/h265 to the end of list if hevc encoding is not allowed. // No need to shift if there is only one supported video codec.
if (encodingOptions.AllowHevcEncoding) if (videoCodecs.Count < 2)
{ {
return; return;
} }
// No need to shift if there is only one supported video codec. // Shift codecs to the end of list if it's not allowed.
if (videoCodecs.Count < 2) var shiftVideoCodecs = new List<string>();
if (!encodingOptions.AllowHevcEncoding)
{ {
return; shiftVideoCodecs.Add("hevc");
shiftVideoCodecs.Add("h265");
}
if (!encodingOptions.AllowAv1Encoding)
{
shiftVideoCodecs.Add("av1");
} }
var shiftVideoCodecs = new[] { "hevc", "h265" };
if (videoCodecs.All(i => shiftVideoCodecs.Contains(i, StringComparison.OrdinalIgnoreCase))) if (videoCodecs.All(i => shiftVideoCodecs.Contains(i, StringComparison.OrdinalIgnoreCase)))
{ {
return; return;

@ -52,6 +52,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
{ {
"libx264", "libx264",
"libx265", "libx265",
"libsvtav1",
"mpeg4", "mpeg4",
"msmpeg4", "msmpeg4",
"libvpx", "libvpx",
@ -69,12 +70,16 @@ namespace MediaBrowser.MediaEncoding.Encoder
"srt", "srt",
"h264_amf", "h264_amf",
"hevc_amf", "hevc_amf",
"av1_amf",
"h264_qsv", "h264_qsv",
"hevc_qsv", "hevc_qsv",
"av1_qsv",
"h264_nvenc", "h264_nvenc",
"hevc_nvenc", "hevc_nvenc",
"av1_nvenc",
"h264_vaapi", "h264_vaapi",
"hevc_vaapi", "hevc_vaapi",
"av1_vaapi",
"h264_v4l2m2m", "h264_v4l2m2m",
"h264_videotoolbox", "h264_videotoolbox",
"hevc_videotoolbox" "hevc_videotoolbox"

@ -49,6 +49,7 @@ public class EncodingOptions
EnableIntelLowPowerHevcHwEncoder = false; EnableIntelLowPowerHevcHwEncoder = false;
EnableHardwareEncoding = true; EnableHardwareEncoding = true;
AllowHevcEncoding = false; AllowHevcEncoding = false;
AllowAv1Encoding = false;
EnableSubtitleExtraction = true; EnableSubtitleExtraction = true;
AllowOnDemandMetadataBasedKeyframeExtractionForExtensions = new[] { "mkv" }; AllowOnDemandMetadataBasedKeyframeExtractionForExtensions = new[] { "mkv" };
HardwareDecodingCodecs = new string[] { "h264", "vc1" }; HardwareDecodingCodecs = new string[] { "h264", "vc1" };
@ -249,6 +250,11 @@ public class EncodingOptions
/// </summary> /// </summary>
public bool AllowHevcEncoding { get; set; } public bool AllowHevcEncoding { get; set; }
/// <summary>
/// Gets or sets a value indicating whether AV1 encoding is enabled.
/// </summary>
public bool AllowAv1Encoding { get; set; }
/// <summary> /// <summary>
/// Gets or sets a value indicating whether subtitle extraction is enabled. /// Gets or sets a value indicating whether subtitle extraction is enabled.
/// </summary> /// </summary>

Loading…
Cancel
Save