diff --git a/FileFlows.Plugin.dll b/FileFlows.Plugin.dll
index b0766dbc..3f23b395 100644
Binary files a/FileFlows.Plugin.dll and b/FileFlows.Plugin.dll differ
diff --git a/FileFlows.Plugin.pdb b/FileFlows.Plugin.pdb
index 1327b086..ef05e11a 100644
Binary files a/FileFlows.Plugin.pdb and b/FileFlows.Plugin.pdb differ
diff --git a/VideoNodes/FfmpegBuilderNodes/EncoderAdjustments/EncoderAdjustment.cs b/VideoNodes/FfmpegBuilderNodes/EncoderAdjustments/EncoderAdjustment.cs
index de5f5eee..f7afadaa 100644
--- a/VideoNodes/FfmpegBuilderNodes/EncoderAdjustments/EncoderAdjustment.cs
+++ b/VideoNodes/FfmpegBuilderNodes/EncoderAdjustments/EncoderAdjustment.cs
@@ -1,3 +1,5 @@
+using FileFlows.VideoNodes.FfmpegBuilderNodes.Models;
+
namespace FileFlows.VideoNodes.FfmpegBuilderNodes.EncoderAdjustments;
///
@@ -9,12 +11,13 @@ public class EncoderAdjustment
/// Run any adjustments that are needed to FFmpeg arguments
///
/// a logger to log to
+ /// the FFmpeg Builder model
/// the FFmpeg args to adjust
/// the adjusted FFMpeg args
- public static List Run(ILogger logger, List args)
+ public static List Run(ILogger logger, FfmpegModel model, List args)
{
if (VaapiAdjustments.IsUsingVaapi(args))
- return new VaapiAdjustments().Run(logger, args);
+ return new VaapiAdjustments().Run(logger, model, args);
return args;
}
diff --git a/VideoNodes/FfmpegBuilderNodes/EncoderAdjustments/IEncoderAdjustment.cs b/VideoNodes/FfmpegBuilderNodes/EncoderAdjustments/IEncoderAdjustment.cs
index ebde284c..207d5f59 100644
--- a/VideoNodes/FfmpegBuilderNodes/EncoderAdjustments/IEncoderAdjustment.cs
+++ b/VideoNodes/FfmpegBuilderNodes/EncoderAdjustments/IEncoderAdjustment.cs
@@ -1,6 +1,18 @@
+using FileFlows.VideoNodes.FfmpegBuilderNodes.Models;
+
namespace FileFlows.VideoNodes.FfmpegBuilderNodes.EncoderAdjustments;
+///
+/// Adjusts the FFmpeg commands
+///
public interface IEncoderAdjustment
{
- List Run(ILogger logger, List args);
+ ///
+ /// Runs the encoder adjustments
+ ///
+ /// the logger to use
+ /// the FFmpeg model
+ /// the FFmpeg arguments
+ /// the updated FFmpeg arguments
+ List Run(ILogger logger, FfmpegModel model, List args);
}
\ No newline at end of file
diff --git a/VideoNodes/FfmpegBuilderNodes/EncoderAdjustments/VaapiAdjustments.cs b/VideoNodes/FfmpegBuilderNodes/EncoderAdjustments/VaapiAdjustments.cs
index c368c9fc..228e8fcb 100644
--- a/VideoNodes/FfmpegBuilderNodes/EncoderAdjustments/VaapiAdjustments.cs
+++ b/VideoNodes/FfmpegBuilderNodes/EncoderAdjustments/VaapiAdjustments.cs
@@ -1,3 +1,4 @@
+using FileFlows.VideoNodes.FfmpegBuilderNodes.Models;
using FileFlows.VideoNodes.Helpers;
namespace FileFlows.VideoNodes.FfmpegBuilderNodes.EncoderAdjustments;
@@ -18,19 +19,32 @@ public class VaapiAdjustments : IEncoderAdjustment
///
/// Runt the adjustments
///
+ /// the logger to use
+ /// the ffmpeg builder model
/// the ffmpeg args
/// the adjusted arguments
- public List Run(ILogger logger, List args)
+ public List Run(ILogger logger, FfmpegModel? model, List args)
{
//logger.ILog("Original VAAPI parameters: \n" + string.Join("\n", args));
int iIndex = args.IndexOf("-i");
if (iIndex >= 0 && VaapiHelper.VaapiLinux)
{
- args.InsertRange(iIndex, new[]
+ if (string.IsNullOrEmpty(model?.Device))
{
- "-vaapi_device",
- VaapiHelper.VaapiRenderDevice
- });
+ args.InsertRange(iIndex, new[]
+ {
+ "-vaapi_device",
+ VaapiHelper.VaapiRenderDevice
+ });
+ }else if (model?.Device != "NONE")
+ {
+ args.InsertRange(iIndex, new[]
+ {
+ "-vaapi_device",
+ model.Device
+ });
+
+ }
}
// "-pix_fmt:v:{index}", "p010le", "-profile:v:{index}", "main10"
diff --git a/VideoNodes/FfmpegBuilderNodes/FfmpegBuilderExecutor.cs b/VideoNodes/FfmpegBuilderNodes/FfmpegBuilderExecutor.cs
index e3826770..e1883dd1 100644
--- a/VideoNodes/FfmpegBuilderNodes/FfmpegBuilderExecutor.cs
+++ b/VideoNodes/FfmpegBuilderNodes/FfmpegBuilderExecutor.cs
@@ -284,7 +284,7 @@ public class FfmpegBuilderExecutor: FfmpegBuilderNode
}
var decodingParameters =
- GetHardwareDecodingArgs(args, localFile, FFMPEG, video?.Stream?.Codec, pxtFormat,
+ GetHardwareDecodingArgs(args, model, localFile, FFMPEG, video?.Stream?.Codec, pxtFormat,
encodingParameters: encodingParameters,
inputPixelFormat: video.Stream.PixelFormat,
destPixelFormat: targetIs10Bit ? "p010le" : (video?.Stream?.Is10Bit == false && video?.Stream?.Is12Bit == false) ? "nv12" : null);
@@ -344,7 +344,7 @@ public class FfmpegBuilderExecutor: FfmpegBuilderNode
}
// make any adjustments needed for hardware devices
- ffArgs = EncoderAdjustment.Run(args.Logger, ffArgs);
+ ffArgs = EncoderAdjustment.Run(args.Logger, model, ffArgs);
var ffmpeg = FFMPEG;
@@ -427,6 +427,7 @@ public class FfmpegBuilderExecutor: FfmpegBuilderNode
/// Gets the hardware decoder to user
///
/// the node parameters
+ /// the FFmpeg Builder model
/// the local file
/// the ffmpeg executable
/// the code to use
@@ -435,7 +436,7 @@ public class FfmpegBuilderExecutor: FfmpegBuilderNode
/// the input pixel format of the source video
/// the true pixel format we will be encoding in
/// the hardware decoding parameters
- internal static string[] GetHardwareDecodingArgs(NodeParameters args, string localFile, string ffmpeg, string codec, string pixelFormat,
+ internal static string[] GetHardwareDecodingArgs(NodeParameters args, FfmpegModel? model, string localFile, string ffmpeg, string codec, string pixelFormat,
List encodingParameters = null, string inputPixelFormat = null, string destPixelFormat = null)
{
var testFile = FileHelper.Combine(args.TempPath, Guid.NewGuid() + ".hwtest.mkv");
@@ -502,7 +503,7 @@ public class FfmpegBuilderExecutor: FfmpegBuilderNode
if (arguments.Any(x => x.Contains("vaapi", StringComparison.InvariantCultureIgnoreCase)))
{
args.Logger?.ILog("VAAPI detected adjusting parameters for testing");
- arguments = new VaapiAdjustments().Run(args.Logger, arguments);
+ arguments = new VaapiAdjustments().Run(args.Logger, model, arguments);
}
args.AdditionalInfoRecorder?.Invoke("Testing", string.Join(" ", hw), 1, new TimeSpan(0, 0, 10));
diff --git a/VideoNodes/FfmpegBuilderNodes/FfmpegBuilderSetDevice.cs b/VideoNodes/FfmpegBuilderNodes/FfmpegBuilderSetDevice.cs
new file mode 100644
index 00000000..9dd2259e
--- /dev/null
+++ b/VideoNodes/FfmpegBuilderNodes/FfmpegBuilderSetDevice.cs
@@ -0,0 +1,32 @@
+namespace FileFlows.VideoNodes.FfmpegBuilderNodes;
+
+///
+/// Sets the device to use
+///
+public class FfmpegBuilderSetDevice : FfmpegBuilderNode
+{
+ ///
+ public override string HelpUrl => "https://fileflows.com/docs/plugins/video-nodes/ffmpeg-builder/set-device";
+
+ ///
+ public override int Outputs => 1;
+
+ ///
+ public override string Icon => "fas fa-plug";
+
+ ///
+ /// Gets or sets the device
+ ///
+ [TextVariable(1)]
+ public string Device { get; set; }
+
+ ///
+ public override int Execute(NodeParameters args)
+ {
+ string device = args.ReplaceVariables(Device ?? string.Empty, stripMissing: true);
+ args.Logger?.ILog("Device: " + device);
+
+ Model.Device = device?.EmptyAsNull() ?? "NONE";
+ return 1;
+ }
+}
\ No newline at end of file
diff --git a/VideoNodes/FfmpegBuilderNodes/Models/FfmpegModel.cs b/VideoNodes/FfmpegBuilderNodes/Models/FfmpegModel.cs
index 9d64e533..01e6fece 100644
--- a/VideoNodes/FfmpegBuilderNodes/Models/FfmpegModel.cs
+++ b/VideoNodes/FfmpegBuilderNodes/Models/FfmpegModel.cs
@@ -90,6 +90,11 @@
///
public TimeSpan? StartTime { get; set; }
+ ///
+ /// Gets or sest the device to use
+ ///
+ public string? Device { get; set; }
+
internal static FfmpegModel CreateModel(VideoInfo info)
{
var model = new FfmpegModel(info);
diff --git a/VideoNodes/FfmpegBuilderNodes/Video/FFmpegBuilderVideoBitrateEncode/AV1.cs b/VideoNodes/FfmpegBuilderNodes/Video/FFmpegBuilderVideoBitrateEncode/AV1.cs
index fe0ffc01..0ae8cb5a 100644
--- a/VideoNodes/FfmpegBuilderNodes/Video/FFmpegBuilderVideoBitrateEncode/AV1.cs
+++ b/VideoNodes/FfmpegBuilderNodes/Video/FFmpegBuilderVideoBitrateEncode/AV1.cs
@@ -60,8 +60,9 @@ public partial class FfmpegBuilderVideoBitrateEncode
/// AV1 QSV encoding
///
/// the bitrate in Kbps
+ /// the device from the FFmpeg Builder Model
/// the encoding parameters
- private static IEnumerable AV1_Qsv(int bitrate)
+ private static IEnumerable AV1_Qsv(int bitrate, string device)
{
var args = new List
{
@@ -71,9 +72,14 @@ public partial class FfmpegBuilderVideoBitrateEncode
"-maxrate", bitrate + "k",
"-bufsize", (bitrate * 2) + "k"
};
- if(VaapiHelper.VaapiLinux)
- args.AddRange(new [] { "-qsv_device", VaapiHelper.VaapiRenderDevice});
-
+ if (VaapiHelper.VaapiLinux)
+ {
+ if(string.IsNullOrEmpty(device))
+ args.AddRange(new[] { "-qsv_device", VaapiHelper.VaapiRenderDevice });
+ else if(device != "NONE")
+ args.AddRange(new[] { "-qsv_device", device });
+ }
+
return args.ToArray();
}
}
\ No newline at end of file
diff --git a/VideoNodes/FfmpegBuilderNodes/Video/FFmpegBuilderVideoBitrateEncode/FfmpegBuilderVideoBitrateEncode.cs b/VideoNodes/FfmpegBuilderNodes/Video/FFmpegBuilderVideoBitrateEncode/FfmpegBuilderVideoBitrateEncode.cs
index 78f4567a..f2c32416 100644
--- a/VideoNodes/FfmpegBuilderNodes/Video/FFmpegBuilderVideoBitrateEncode/FfmpegBuilderVideoBitrateEncode.cs
+++ b/VideoNodes/FfmpegBuilderNodes/Video/FFmpegBuilderVideoBitrateEncode/FfmpegBuilderVideoBitrateEncode.cs
@@ -87,7 +87,7 @@ public partial class FfmpegBuilderVideoBitrateEncode:VideoEncodeBase
{
bool tenBit = Codec == CODEC_AV1_10BIT || stream.Stream.Is10Bit;
args.Logger?.ILog("10 Bit: " + tenBit);
- var encodingParameters = AV1(args, tenBit, Bitrate, encoder).ToArray();
+ var encodingParameters = AV1(args, tenBit, Bitrate, encoder, Model.Device).ToArray();
args.Logger?.ILog("Encoding Parameters: " +
string.Join(" ", encodingParameters.Select(x => x.Contains(" ") ? "\"" + x + "\"" : x)));
@@ -138,14 +138,14 @@ public partial class FfmpegBuilderVideoBitrateEncode:VideoEncodeBase
return modified.ToArray();
}
- internal static IEnumerable GetEncodingParameters(NodeParameters args, string codec, int bitrate, string encoder, float fps)
+ internal static IEnumerable GetEncodingParameters(NodeParameters args, string codec, int bitrate, string encoder, float fps, string device)
{
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"));
+ return AV1(args, codec == CODEC_AV1_10BIT, bitrate, encoder, device).Select(x => x.Replace("{index}", "0"));
throw new Exception("Unsupported codec: " + codec);
}
@@ -265,7 +265,7 @@ public partial class FfmpegBuilderVideoBitrateEncode:VideoEncodeBase
}
- private static IEnumerable AV1(NodeParameters args, bool tenBit, int bitrate, string encoder)
+ private static IEnumerable AV1(NodeParameters args, bool tenBit, int bitrate, string encoder, string device)
{
// 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 parameters = new List();
@@ -275,14 +275,14 @@ public partial class FfmpegBuilderVideoBitrateEncode:VideoEncodeBase
else if(encoder == ENCODER_NVIDIA)
parameters.AddRange(AV1_Nvidia(bitrate));
else if(encoder == ENCODER_QSV)
- parameters.AddRange(AV1_Qsv(bitrate));
+ parameters.AddRange(AV1_Qsv(bitrate, device));
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));
+ parameters.AddRange(AV1_Qsv(bitrate, device));
else if (CanUseHardwareEncoding.CanProcess_Amd_AV1(args))
parameters.AddRange(AV1_Amd(bitrate));
else
diff --git a/VideoNodes/FfmpegBuilderNodes/Video/FfmpegBuilderVideoEncode/AV1.cs b/VideoNodes/FfmpegBuilderNodes/Video/FfmpegBuilderVideoEncode/AV1.cs
index 546da653..f825058f 100644
--- a/VideoNodes/FfmpegBuilderNodes/Video/FfmpegBuilderVideoEncode/AV1.cs
+++ b/VideoNodes/FfmpegBuilderNodes/Video/FfmpegBuilderVideoEncode/AV1.cs
@@ -85,10 +85,11 @@ public partial class FfmpegBuilderVideoEncode
///
/// AV1 QSV encoding
///
+ /// the device from the FFmpeg Builder model
/// the quality
/// the speed
/// the encoding parameters
- private static IEnumerable AV1_Qsv(int quality, string speed)
+ private static IEnumerable AV1_Qsv(string device, int quality, string speed)
{
switch (speed)
{
@@ -109,9 +110,14 @@ public partial class FfmpegBuilderVideoEncode
"-global_quality:v", quality.ToString(),
"-preset", speed
};
- if(VaapiHelper.VaapiLinux)
- args.AddRange(new [] { "-qsv_device", VaapiHelper.VaapiRenderDevice});
-
+ if (VaapiHelper.VaapiLinux)
+ {
+ if(string.IsNullOrEmpty(device))
+ args.AddRange(new[] { "-qsv_device", VaapiHelper.VaapiRenderDevice });
+ else if(device != "NONE")
+ args.AddRange(new[] { "-qsv_device", device});
+ }
+
return args.ToArray();
}
}
\ No newline at end of file
diff --git a/VideoNodes/FfmpegBuilderNodes/Video/FfmpegBuilderVideoEncode/FfmpegBuilderVideoEncode.cs b/VideoNodes/FfmpegBuilderNodes/Video/FfmpegBuilderVideoEncode/FfmpegBuilderVideoEncode.cs
index 8df744e4..6f656fba 100644
--- a/VideoNodes/FfmpegBuilderNodes/Video/FfmpegBuilderVideoEncode/FfmpegBuilderVideoEncode.cs
+++ b/VideoNodes/FfmpegBuilderNodes/Video/FfmpegBuilderVideoEncode/FfmpegBuilderVideoEncode.cs
@@ -130,7 +130,7 @@ public partial class FfmpegBuilderVideoEncode:VideoEncodeBase
{
bool tenBit = Codec == CODEC_AV1_10BIT || stream.Stream.Is10Bit;
args.Logger?.ILog("10 Bit: " + tenBit);
- var encodingParameters = AV1(args, tenBit, Quality, encoder, Speed).ToArray();
+ var encodingParameters = AV1(args, tenBit, Quality, encoder, Speed, Model.Device).ToArray();
args.Logger?.ILog("Encoding Parameters: " +
string.Join(" ", encodingParameters.Select(x => x.Contains(" ") ? "\"" + x + "\"" : x)));
stream.EncodingParameters.AddRange(encodingParameters);
@@ -154,14 +154,14 @@ public partial class FfmpegBuilderVideoEncode:VideoEncodeBase
return 1;
}
- internal static IEnumerable GetEncodingParameters(NodeParameters args, string codec, int quality, string encoder, float fps, string speed)
+ internal static IEnumerable GetEncodingParameters(NodeParameters args, string codec, int quality, string encoder, float fps, string speed, string? device = null)
{
if (codec == CODEC_H264)
return H264(args, false, quality, encoder, speed).Select(x => x.Replace("{index}", "0"));
if (codec == CODEC_H265 || codec == CODEC_H265_10BIT)
return H265(null, args, codec == CODEC_H265_10BIT, quality, encoder, fps, speed).Select(x => x.Replace("{index}", "0"));
if(codec == CODEC_AV1)
- return AV1(args, codec == CODEC_AV1_10BIT, quality, encoder, speed).Select(x => x.Replace("{index}", "0"));
+ return AV1(args, codec == CODEC_AV1_10BIT, quality, encoder, speed, device).Select(x => x.Replace("{index}", "0"));
throw new Exception("Unsupported codec: " + codec);
}
@@ -281,7 +281,7 @@ public partial class FfmpegBuilderVideoEncode:VideoEncodeBase
}
- private static IEnumerable AV1(NodeParameters args, bool tenBit, int quality, string encoder, string speed)
+ private static IEnumerable AV1(NodeParameters args, bool tenBit, int quality, string encoder, string speed, string device)
{
// 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 parameters = new List();
@@ -291,14 +291,14 @@ public partial class FfmpegBuilderVideoEncode:VideoEncodeBase
else if(encoder == ENCODER_NVIDIA)
parameters.AddRange(AV1_Nvidia(quality, speed));
else if(encoder == ENCODER_QSV)
- parameters.AddRange(AV1_Qsv(quality, speed));
+ parameters.AddRange(AV1_Qsv(device, quality, speed));
else if(encoder == ENCODER_AMF)
parameters.AddRange(AV1_Amd(quality, speed));
else if (CanUseHardwareEncoding.CanProcess_Nvidia_AV1(args))
parameters.AddRange(AV1_Nvidia(quality, speed));
else if (CanUseHardwareEncoding.CanProcess_Qsv_AV1(args))
- parameters.AddRange(AV1_Qsv(quality, speed));
+ parameters.AddRange(AV1_Qsv(device, quality, speed));
else if (CanUseHardwareEncoding.CanProcess_Amd_AV1(args))
parameters.AddRange(AV1_Amd(quality, speed));
else
diff --git a/VideoNodes/LogicalNodes/VideoHasErrors.cs b/VideoNodes/LogicalNodes/VideoHasErrors.cs
index bf5d2e53..e20b271a 100644
--- a/VideoNodes/LogicalNodes/VideoHasErrors.cs
+++ b/VideoNodes/LogicalNodes/VideoHasErrors.cs
@@ -94,7 +94,7 @@ public class VideoHasErrors: VideoNode
if (useHardwareDecoding)
{
var hardwareDecodingArgs =
- FfmpegBuilderNodes.FfmpegBuilderExecutor.GetHardwareDecodingArgs(args, filename, ffmpegPath,
+ FfmpegBuilderNodes.FfmpegBuilderExecutor.GetHardwareDecodingArgs(args, null, filename, ffmpegPath,
video?.Codec, video?.PixelFormat);
if (hardwareDecodingArgs?.Any() == true)
{
diff --git a/VideoNodes/Tests/VaapiAdjustmentTests.cs b/VideoNodes/Tests/VaapiAdjustmentTests.cs
index 9524f659..42d506b2 100644
--- a/VideoNodes/Tests/VaapiAdjustmentTests.cs
+++ b/VideoNodes/Tests/VaapiAdjustmentTests.cs
@@ -1,6 +1,7 @@
#if(DEBUG)
using FileFlows.VideoNodes.FfmpegBuilderNodes.EncoderAdjustments;
+using FileFlows.VideoNodes.FfmpegBuilderNodes.Models;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace VideoNodes.Tests;
@@ -59,7 +60,7 @@ public class VaapiAdjustmentTests: TestBase
};
var logger = new TestLogger();
- var updated = new VaapiAdjustments().Run(logger, inputParameters);
+ var updated = new VaapiAdjustments().Run(logger, null!, inputParameters);
Assert.AreEqual("-vf", updated[9]);
Assert.AreEqual("format=nv12,hwupload,scale_vaapi=1280:-2", updated[10]);
int index = updated.FindIndex(x => x.StartsWith("-filter:v"));
@@ -119,7 +120,7 @@ public class VaapiAdjustmentTests: TestBase
};
var logger = new TestLogger();
- var updated = new VaapiAdjustments().Run(logger, inputParameters);
+ var updated = new VaapiAdjustments().Run(logger, null!, inputParameters);
Assert.AreEqual("-vf", updated[9]);
Assert.AreEqual("format=nv12,hwupload,scale_vaapi=1280:-2", updated[10]);
Assert.IsFalse(updated.Any(x => x.StartsWith("-filter:v")));
diff --git a/VideoNodes/i18n/en.json b/VideoNodes/i18n/en.json
index 2c302386..0d0e23f1 100644
--- a/VideoNodes/i18n/en.json
+++ b/VideoNodes/i18n/en.json
@@ -625,6 +625,17 @@
"Index-Help": "The index of the track to set as default, only used if language is not specified."
}
},
+ "FfmpegBuilderSetDevice": {
+ "Label": "FFMPEG Builder: Set Device",
+ "Description": "Sets the device to use for hardware encoding/decoder if the encoder/decoder supports it.",
+ "Outputs": {
+ "1": "Device set"
+ },
+ "Fields": {
+ "Device": "Device",
+ "Device-Help": "The path to the device, or leave blank if no device should be specified."
+ }
+ },
"FfmpegBuilderSetFps": {
"Label": "FFMPEG Builder: Set FPS",
"Description": "Set the frames per second (FPS) in the FFmpeg Builder",