fix: 03_Encode_AV1 - align params with Flow model (TargetPercent/MaxratePercent), add size safety net, add JSDoc

This commit is contained in:
sascha 2026-07-17 19:38:32 +02:00
parent 858ceb563a
commit 02c1db0cbc

View file

@ -1,13 +1,33 @@
function Script(CQ, Preset, SizePercent, BufsizeMultiplier, AQStrength, RcLookahead)
/**
* @name 03_Encode_AV1_NVENC
* @description AV1-Encode via NVIDIA NVENC fuer 4K-Remux Material.
* VBR mit CQ, maxrate = TargetPercent der Quelle, bufsize = MaxratePercent * BufsizeMultiplier.
* CUDA HW-Decode. HDR/DV-aware. Audio: EAC3-Kompatspur bei DTS, sonst copy.
* Subtitles 1:1. GROESSEN-SICHERHEITSNETZ: Output <= Original (Toleranz 5%).
* @author Sascha + Trulla
* @revision 2
* @output Encode erfolgreich
* @output Skip / Fehler
* @param {int} TargetPercent Ziel-Bitrate als % der Quelle (z.B. 50 = halbe Bitrate)
* @param {int} MaxratePercent Peak-Cap als % der Quelle (z.B. 60)
* @param {int} BufsizeMultiplier bufsize = Maxrate * BufsizeMultiplier
* @param {int} RcLookahead NVENC rc-lookahead Frames
* @param {int} CQ Constant Quality (niedriger = besser, Default 24)
* @param {string} Preset NVENC Preset p1..p7 (Default p7 = langsamste/beste)
* @param {int} AQStrength Adaptive Quantization (Default 15)
*/
function Script(TargetPercent, MaxratePercent, BufsizeMultiplier, RcLookahead, CQ, Preset, AQStrength)
{
TargetPercent = TargetPercent || 50;
MaxratePercent = MaxratePercent || 60;
BufsizeMultiplier = BufsizeMultiplier || 2;
RcLookahead = RcLookahead || 40;
CQ = CQ || 24;
Preset = Preset || 'p7';
SizePercent = SizePercent || 60;
BufsizeMultiplier = BufsizeMultiplier || 2;
AQStrength = AQStrength || 15;
RcLookahead = RcLookahead || 64;
let SizeFactor = SizePercent / 100;
let TargetFactor = TargetPercent / 100;
let MaxrateFactor = MaxratePercent / 100;
// ─────────────────────────────────────────────────────────────────────────
// Variables.vi.VideoInfo ist in dieser FileFlows-Version im ScriptNode LEER
@ -69,7 +89,8 @@ function Script(CQ, Preset, SizePercent, BufsizeMultiplier, AQStrength, RcLookah
if (bitrateBps <= 0) { Logger.ELog('Bitrate nicht ermittelbar - Skip'); return 2; }
let srcMbps = bitrateBps / 1000000;
let maxrateMbps = Math.round(srcMbps * SizeFactor * 10) / 10;
let targetMbps = Math.round(srcMbps * TargetFactor * 10) / 10;
let maxrateMbps = Math.round(srcMbps * MaxrateFactor * 10) / 10;
let bufsizeMbps = Math.round(maxrateMbps * BufsizeMultiplier * 10) / 10;
// HDR / Dolby Vision Detection
@ -85,8 +106,9 @@ function Script(CQ, Preset, SizePercent, BufsizeMultiplier, AQStrength, RcLookah
let forceSDR = (isDV && dvProfile === 5);
Logger.ILog('Quelle: ' + srcMbps.toFixed(1) + ' Mbit/s');
Logger.ILog('Cap : maxrate=' + maxrateMbps + ' Mbit/s bufsize=' + bufsizeMbps + ' Mbit/s (<= ' +
SizePercent + '% der Quelle)');
Logger.ILog('Target : ' + targetMbps + ' Mbit/s (' + TargetPercent + '%)');
Logger.ILog('Cap : maxrate=' + maxrateMbps + ' Mbit/s bufsize=' + bufsizeMbps + ' Mbit/s (' +
MaxratePercent + '% der Quelle)');
Logger.ILog('Color : HDR10=' + isHDR10 + ' DV=' + isDV + ' Profile=' + dvProfile + ' forceSDR=' + forceSDR);
// ── ffmpeg-Argumente
@ -101,7 +123,7 @@ function Script(CQ, Preset, SizePercent, BufsizeMultiplier, AQStrength, RcLookah
'-pix_fmt', 'p010le',
'-rc', 'vbr',
'-cq', '' + CQ,
'-b:v', '0',
'-b:v', targetMbps + 'M',
'-preset', Preset,
'-tune', 'hq',
'-multipass', 'fullres',
@ -198,6 +220,25 @@ function Script(CQ, Preset, SizePercent, BufsizeMultiplier, AQStrength, RcLookah
return 2;
}
// ── GROESSEN-SICHERHEITSNETZ ──────────────────────────────────
// Output darf nicht wesentlich groesser sein als die Quelle.
// Toleranz: 5% (fuer Audio-Stream-Unterschiede / Metadaten).
// Bei Ueberschreitung: Encode verwerfen, Original behalten, Warnung.
let origSizeStat = Flow.Execute({ command: '/usr/bin/stat', argumentList: ['-c', '%s', inputFile] });
let origSize = parseInt((origSizeStat && origSizeStat.standardOutput) ? origSizeStat.standardOutput.trim() : '0', 10) || 0;
let newSizeStat = Flow.Execute({ command: '/usr/bin/stat', argumentList: ['-c', '%s', outFile] });
let newSize = parseInt((newSizeStat && newSizeStat.standardOutput) ? newSizeStat.standardOutput.trim() : '0', 10) || 0;
if (origSize > 0 && newSize > 0) {
let growthPct = ((newSize - origSize) / origSize) * 100;
Logger.ILog('Groesse: orig=' + origSize + ' bytes, output=' + newSize + ' bytes, growth=' + growthPct.toFixed(1) + '%');
if (growthPct > 5) {
Logger.WLog('GROESSEN-WARNUNG: Output ' + growthPct.toFixed(1) + '% groesser als Quelle -> Encode verworfen, Original bleibt.');
Flow.Execute({ command: '/bin/rm', argumentList: ['-f', outFile] });
return 2;
}
}
Flow.SetWorkingFile(outFile);
Logger.ILog('AV1 Encode erfolgreich -> ' + outFile);
return 1;