diff --git a/fileflows/scripts/02_Detect_1080p_HighBitrate.js b/fileflows/scripts/02_Detect_1080p_HighBitrate.js new file mode 100644 index 0000000..36b06bd --- /dev/null +++ b/fileflows/scripts/02_Detect_1080p_HighBitrate.js @@ -0,0 +1,72 @@ +function Script(MinHeight, MaxHeight, MinBitrateMbps) +{ + MinHeight = MinHeight || 720; + MaxHeight = MaxHeight || 1080; + MinBitrateMbps = MinBitrateMbps || 8; + + // Variables.vi.VideoInfo ist im ScriptNode leer (verifiziert 2026-07-06) -> ffprobe direkt. + function probeInfo() { + var probe = null; + try { probe = Flow.GetToolPath('ffprobe'); } catch (e) {} + if (!probe) probe = Variables['ffprobe'] || 'ffprobe'; + var res = Flow.Execute({ + command: probe, + argumentList: ['-v', 'quiet', '-print_format', 'json', + '-show_format', '-show_streams', Flow.WorkingFile] + }); + if (!res || res.exitCode !== 0) { Logger.WLog('ffprobe fehlgeschlagen'); return null; } + var j; + try { j = JSON.parse(res.standardOutput || res.output || ''); } catch (e) { Logger.WLog('ffprobe JSON-Fehler: ' + e); return null; } + var streams = j.streams || []; + var fmtBr = parseInt((j.format && j.format.bit_rate) || 0, 10) || 0; + function tagBps(s) { var t = s.tags || {}; return parseInt(t.BPS || t['BPS-eng'] || t.bps || 0, 10) || 0; } + var vids = [], auds = []; + for (var i = 0; i < streams.length; i++) { + var s = streams[i], disp = s.disposition || {}; + if (s.codec_type === 'video') { + if (disp.attached_pic === 1 || s.codec_name === 'mjpeg' || s.codec_name === 'png') continue; + vids.push({ Width: s.width || 0, Height: s.height || 0, Codec: (s.codec_name || ''), Bitrate: tagBps(s) || 0 }); + } else if (s.codec_type === 'audio') { + var t = s.tags || {}; + auds.push({ Language: t.language || '', Codec: (s.codec_name || '') }); + } + } + return { Bitrate: fmtBr, VideoStreams: vids, AudioStreams: auds }; + } + + let vi = probeInfo(); + let v = (vi && vi.VideoStreams && vi.VideoStreams.length > 0) ? vi.VideoStreams[0] : null; + + if (!v) { + Logger.ELog('Kein Video-Stream ermittelbar (ffprobe) - 1:1 Move'); + return 2; + } + + let height = v.Height || 0; + let codec = (v.Codec || '').toLowerCase(); + let bitrateBps = v.Bitrate || 0; + if (bitrateBps <= 0 && vi.Bitrate) bitrateBps = Math.round(vi.Bitrate * 0.92); + let bitrateMbps = bitrateBps > 0 ? (bitrateBps / 1000000) : 0; + + // DE-Spur pruefen - ohne DE macht der HEVC-Encoder keinen Sinn. + let audioStreams = (vi && vi.AudioStreams) ? vi.AudioStreams : []; + let hasGerman = audioStreams.some(function (a) { + let lang = (a.Language || '').toLowerCase().trim(); + return lang === 'ger' || lang === 'deu' || lang === 'de'; + }); + + let inRange = (height >= MinHeight && height <= MaxHeight); + let highBR = bitrateMbps > MinBitrateMbps; + + Logger.ILog('Video: codec=' + codec + ' height=' + height + ' bitrate=' + + (bitrateMbps > 0 ? bitrateMbps.toFixed(2) + ' Mbit/s' : 'unbekannt')); + Logger.ILog('Checks: inRange[' + MinHeight + '-' + MaxHeight + ']=' + inRange + + ' >' + MinBitrateMbps + 'Mbit=' + highBR + ' DE=' + hasGerman); + + if (!inRange) { Logger.ILog('Hoehe ' + height + ' ausserhalb ' + MinHeight + '-' + MaxHeight + ' - 1:1 Move'); return 2; } + if (!highBR) { Logger.ILog('Bitrate <= ' + MinBitrateMbps + ' Mbit/s - 1:1 Move'); return 2; } + if (!hasGerman) { Logger.ILog('Keine deutsche Audiospur - 1:1 Move'); return 2; } + + Logger.ILog('-> 1080p Re-Encode Kandidat fuer HEVC NVENC'); + return 1; +}