diff --git a/VideoNodes/FfmpegBuilderNodes/Video/FfmpegBuilderSetFps.cs b/VideoNodes/FfmpegBuilderNodes/Video/FfmpegBuilderSetFps.cs new file mode 100644 index 00000000..a69102e9 --- /dev/null +++ b/VideoNodes/FfmpegBuilderNodes/Video/FfmpegBuilderSetFps.cs @@ -0,0 +1,114 @@ +namespace FileFlows.VideoNodes.FfmpegBuilderNodes; + +/// +/// FFmpeg Builder flow element that sets the FPS of the resulting video +/// +public class FfmpegBuilderSetFps:FfmpegBuilderNode +{ + /// + /// The number of outputs for this flow element + /// + public override int Outputs => 2; + /// + /// The Help URL for this flow element + /// + public override string HelpUrl => "https://fileflows.com/docs/plugins/video-nodes/ffmpeg-builder/set-fps"; + /// + /// Gets the icon to show for this flow element + /// + public override string Icon => "fas fa-stopwatch"; + + /// + /// Gets or sets the FPS to use + /// + [DefaultValue(30f)] + [NumberFloat(1)] + public float Fps { get; set; } + + /// + /// Gets or sets if the FPS should be adjusted only if the current FPS is over the current + /// + [Boolean(2)] + public bool OnlyIfHigher { get; set; } + + + /// + /// Executes the node logic based on the provided parameters. + /// + /// Node parameters. + /// An integer representing the execution result. + public override int Execute(NodeParameters args) + { + double desiredFps = Fps; + + VideoInfo videoInfo = GetVideoInfo(args); + if (videoInfo == null || !videoInfo.VideoStreams?.Any() == true) + { + args.Logger?.ELog("No video streams found."); + return -1; + } + + int currentFps = (int)Math.Ceiling(videoInfo.VideoStreams[0].FramesPerSecond); + currentFps = FixHighFrameRateBug(currentFps); + + var ffmpegModel = GetModel(); + if (ffmpegModel == null) + { + args.Logger?.ELog("FFMPEG Builder variable not found"); + return -1; + } + + // check for video stream + var videoStream = ffmpegModel.VideoStreams[0]; + if (videoStream == null) + { + args.Logger?.ELog("FFMPEG Builder no video stream found"); + return -1; + } + + if (Math.Abs(currentFps - desiredFps) < 0.05f) + { + args.Logger?.ILog("The frame rate matches, so does not need changing"); + return 2; + } + + if (currentFps > desiredFps) + { + args.Logger?.ILog($"The frame rate {currentFps}fps is higher than the desired {desiredFps}fps, so will be changed"); + videoStream.Filter.Add($"fps=fps={desiredFps}"); + return 1; + } + + if (currentFps < desiredFps) + { + if (OnlyIfHigher) + { + args.Logger?.ILog($"The frame rate {currentFps}fps is lower than the desired {desiredFps}fps, and (Only If Higher) was selected, so no change needed"); + return 2; + } + + args.Logger?.ILog($"The frame rate {currentFps}fps is lower than the desired {desiredFps}fps, so will be changed"); + videoStream.Filter.Add($"fps=fps={desiredFps}"); + return 1; + } + + args.Logger?.ILog("The frame rate is unknown"); + return 2; + } + + /// + /// Fixes a bug related to high frame rates by adjusting the current frame rate. + /// + /// Current frame rate. + /// Adjusted frame rate. + private int FixHighFrameRateBug(int currentFps) + { + if (currentFps > 200) + { + // Adjust the current frame rate for high frame rate bug + return (int)(currentFps / 100f); + } + + return currentFps; + } +} diff --git a/VideoNodes/VideoNodes.en.json b/VideoNodes/VideoNodes.en.json index 9533a944..88a10aef 100644 --- a/VideoNodes/VideoNodes.en.json +++ b/VideoNodes/VideoNodes.en.json @@ -546,6 +546,20 @@ "Index-Help": "The index of the track to set as default, only used if language is not specified." } }, + "FfmpegBuilderSetFps": { + "Label": "FFMPEG Builder: Set FPS", + "Description": "Set the frames per second (FPS) in the FFmpeg Builder", + "Outputs": { + "1": "FPS updated", + "2": "No changes were necessary" + }, + "Fields": { + "Fps": "FPS", + "Fps-Help": "The desired FPS, if the input FPS and the desired FPS do not match then FFMPEG will convert it, e.g (23.976, 24, 30, 60).", + "OnlyIfHigher": "Only If Higher", + "OnlyIfHigher-Help": "If the FPS should be adjusted only if the current FPS is more than the current." + } + }, "FfmpegBuilderSetTrackTitles": { "Label": "FFMPEG Builder: Set Track Titles", "Description": "Set track titles based on a formatter in the FFmpeg builder.",