mirror of
https://github.com/revenz/FileFlowsPlugins.git
synced 2026-01-06 09:29:33 -06:00
130 lines
4.7 KiB
C#
130 lines
4.7 KiB
C#
using FileFlows.Plugin;
|
|
using FileFlows.VideoNodes.FfmpegBuilderNodes.Models;
|
|
|
|
namespace FileFlows.VideoNodes.FfmpegBuilderNodes
|
|
{
|
|
public class FfmpegBuilderExecutor: FfmpegBuilderNode
|
|
{
|
|
public override string Icon => "far fa-file-video";
|
|
public override int Inputs => 1;
|
|
public override int Outputs => 2;
|
|
public override FlowElementType Type => FlowElementType.BuildEnd;
|
|
|
|
public override string HelpUrl => "https://docs.fileflows.com/plugins/video-nodes/ffmpeg-builder";
|
|
|
|
public override bool NoEditorOnAdd => true;
|
|
|
|
[DefaultValue(true)]
|
|
[Boolean(1)]
|
|
public bool HardwareDecoding { get; set; }
|
|
|
|
public override int Execute(NodeParameters args)
|
|
{
|
|
var model = this.Model;
|
|
List<string> ffArgs = new List<string>();
|
|
ffArgs.AddRange(new[] { "-strict", "-2" }); // allow experimental stuff
|
|
ffArgs.AddRange(new[] { "-fflags", "+genpts" }); //Generate missing PTS if DTS is present.
|
|
|
|
if(model.CustomParameters?.Any() == true)
|
|
ffArgs.AddRange(model.CustomParameters);
|
|
|
|
bool hasChange = false;
|
|
int actualIndex = 0;
|
|
int currentType = 0;
|
|
foreach (var item in model.VideoStreams.Select((x, index) => (stream: (FfmpegStream)x, index, type: 1)).Union(
|
|
model.AudioStreams.Select((x, index) => (stream: (FfmpegStream)x, index, type: 2))).Union(
|
|
model.SubtitleStreams.Select((x, index) => (stream: (FfmpegStream)x, index, type: 3))))
|
|
{
|
|
if (item.stream.Deleted)
|
|
{
|
|
hasChange = true;
|
|
continue;
|
|
}
|
|
if (currentType != item.type)
|
|
{
|
|
actualIndex = 0;
|
|
currentType = item.type;
|
|
}
|
|
|
|
ffArgs.AddRange(item.stream.GetParameters(actualIndex));
|
|
hasChange |= item.stream.HasChange | item.stream.ForcedChange;
|
|
++actualIndex;
|
|
}
|
|
|
|
if(model.MetadataParameters?.Any() == true)
|
|
{
|
|
hasChange = true;
|
|
ffArgs.AddRange(model.MetadataParameters);
|
|
}
|
|
|
|
if (model.ForceEncode == false && hasChange == false && (string.IsNullOrWhiteSpace(model.Extension) || args.WorkingFile.ToLower().EndsWith("." + model.Extension.ToLower())))
|
|
return 2; // nothing to do
|
|
|
|
string extension = model.Extension?.EmptyAsNull() ?? "mkv";
|
|
|
|
List<string> startArgs = new List<string>();
|
|
if (model.InputFiles?.Any() == false)
|
|
model.InputFiles.Add(args.WorkingFile);
|
|
else
|
|
model.InputFiles[0] = args.WorkingFile;
|
|
|
|
startArgs.AddRange(new[] {
|
|
"-probesize", VideoInfoHelper.ProbeSize + "M"
|
|
});
|
|
|
|
if (HardwareDecoding)
|
|
{
|
|
startArgs.AddRange(GetHardwareDecodingArgs());
|
|
}
|
|
|
|
foreach (string file in model.InputFiles)
|
|
{
|
|
startArgs.Add("-i");
|
|
startArgs.Add(file);
|
|
}
|
|
startArgs.Add("-y");
|
|
ffArgs = startArgs.Concat(ffArgs).ToList();
|
|
|
|
|
|
if (Encode(args, FFMPEG, ffArgs, extension, dontAddInputFile: true) == false)
|
|
return -1;
|
|
|
|
return 1;
|
|
}
|
|
|
|
internal string[] GetHardwareDecodingArgs()
|
|
{
|
|
string testFile = Path.Combine(Args.TempPath, Guid.NewGuid() + ".hwtest.mkv");
|
|
foreach(var hw in new [] { "cuda", "qsv", "dxva2", "d3d11va", "opencl" })
|
|
{
|
|
// ffmpeg -y -hwaccel qsvf -f lavfi -i color=color=red -frames:v 10 test.mkv
|
|
try
|
|
{
|
|
var result = Args.Execute(new ExecuteArgs
|
|
{
|
|
Command = FFMPEG,
|
|
ArgumentList = new[]
|
|
{
|
|
"-y",
|
|
"-hwaccel", hw,
|
|
"-f", "lavfi",
|
|
"-i", "color=color=red",
|
|
"-frames:v", "10",
|
|
testFile
|
|
}
|
|
});
|
|
if (result.ExitCode == 0)
|
|
{
|
|
Args.Logger?.ILog("Supported hardware decoding detected: " + hw);
|
|
return new[] { "-hwaccel", hw };
|
|
}
|
|
}
|
|
catch (Exception) { }
|
|
}
|
|
|
|
Args.Logger?.ILog("No hardware decoding availble");
|
|
return new string[] { };
|
|
}
|
|
}
|
|
}
|