chore: add 01_Detect_4K_Remux.js from live FileFlows export
This commit is contained in:
parent
12cfca26d1
commit
7aa14490b3
1 changed files with 109 additions and 0 deletions
109
fileflows/scripts/01_Detect_4K_Remux.js
Normal file
109
fileflows/scripts/01_Detect_4K_Remux.js
Normal file
|
|
@ -0,0 +1,109 @@
|
||||||
|
function Script(MinWidth, MinSourceMbps)
|
||||||
|
{
|
||||||
|
MinWidth = MinWidth || 3000;
|
||||||
|
MinSourceMbps = MinSourceMbps || 15;
|
||||||
|
|
||||||
|
// ─────────────────────────────────────────────────────────────────────────
|
||||||
|
// WICHTIG (verifiziert 2026-07-06): Variables.vi.VideoInfo wird in dieser
|
||||||
|
// FileFlows-Version im ScriptNode NICHT befuellt (0/7 Laeufe hatten vi-Daten,
|
||||||
|
// die "loadVi"-Warteschleife war wirkungslos). Der native VideoInfo-Zugriff
|
||||||
|
// laeuft nur ueber den FFmpeg-Builder-Node, nicht im Script.
|
||||||
|
// -> Verlaesslicher Weg: ffprobe direkt aufrufen und JSON parsen.
|
||||||
|
// Liefert echte Kanalzahlen (6/8) statt Layout-Strings ("5.1").
|
||||||
|
// ─────────────────────────────────────────────────────────────────────────
|
||||||
|
function probeInfo() {
|
||||||
|
var probe = null;
|
||||||
|
try { probe = Flow.GetToolPath('ffprobe'); } catch (e) {}
|
||||||
|
if (!probe) probe = Variables['ffprobe'] || 'ffprobe';
|
||||||
|
var input = Flow.WorkingFile;
|
||||||
|
var res = Flow.Execute({
|
||||||
|
command: probe,
|
||||||
|
argumentList: ['-v', 'quiet', '-print_format', 'json',
|
||||||
|
'-show_format', '-show_streams', input]
|
||||||
|
});
|
||||||
|
if (!res || res.exitCode !== 0) { Logger.WLog('ffprobe fehlgeschlagen (exit=' + (res ? res.exitCode : '?') + ')'); return null; }
|
||||||
|
var raw = res.standardOutput || res.output || '';
|
||||||
|
var j;
|
||||||
|
try { j = JSON.parse(raw); } catch (e) { Logger.WLog('ffprobe JSON parse-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') {
|
||||||
|
// cover/poster (attached_pic, mjpeg, png) ignorieren
|
||||||
|
if (disp.attached_pic === 1 || s.codec_name === 'mjpeg' || s.codec_name === 'png') continue;
|
||||||
|
var dovi = (s.side_data_list || []).some(function (x) {
|
||||||
|
var t = ('' + (x.side_data_type || '')).toLowerCase();
|
||||||
|
return t.indexOf('dovi') !== -1 || t.indexOf('dolby vision') !== -1;
|
||||||
|
});
|
||||||
|
var trc = ('' + (s.color_transfer || ''));
|
||||||
|
vids.push({
|
||||||
|
Width: s.width || 0, Height: s.height || 0,
|
||||||
|
Codec: (s.codec_name || ''),
|
||||||
|
Bitrate: tagBps(s) || 0,
|
||||||
|
ColorTransfer: trc, ColorPrimaries: s.color_primaries || '', ColorSpace: s.color_space || '',
|
||||||
|
PixelFormat: s.pix_fmt || '',
|
||||||
|
DolbyVision: dovi,
|
||||||
|
// P7 hat HDR10-Base-Layer (smpte2084), P5 ist ICtCp (kein smpte2084)
|
||||||
|
DolbyVisionProfile: dovi ? (trc.indexOf('smpte2084') !== -1 ? 7 : 5) : null
|
||||||
|
});
|
||||||
|
} else if (s.codec_type === 'audio') {
|
||||||
|
var t = s.tags || {};
|
||||||
|
auds.push({
|
||||||
|
Language: t.language || '', Codec: (s.codec_name || ''),
|
||||||
|
Channels: s.channels || 0, ChannelLayout: s.channel_layout || '',
|
||||||
|
Title: t.title || '', Profile: s.profile || '',
|
||||||
|
Default: (disp.default === 1), Bitrate: tagBps(s) || 0
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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) - kann 4K-Remux nicht bewerten');
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
let width = v.Width || 0;
|
||||||
|
let codec = (v.Codec || '').toLowerCase();
|
||||||
|
let bitrateBps = v.Bitrate || 0;
|
||||||
|
// Video-Bitrate fehlt (kein BPS-Tag) -> aus Container-Gesamtbitrate schaetzen (~92%)
|
||||||
|
if (bitrateBps <= 0 && vi.Bitrate) bitrateBps = Math.round(vi.Bitrate * 0.92);
|
||||||
|
let bitrateMbps = bitrateBps > 0 ? (bitrateBps / 1000000) : 0;
|
||||||
|
|
||||||
|
// Dateiname aus den flachen Punkt-Keys (Variables.file als Objekt existiert NICHT in dieser Version)
|
||||||
|
let fileName = Variables['file.Orig.FullName'] || Variables['file.FullName']
|
||||||
|
|| Variables['file.Name'] || '';
|
||||||
|
if (!fileName) { try { fileName = Flow.WorkingFile || ''; } catch (e) {} }
|
||||||
|
|
||||||
|
let is4K = width >= MinWidth;
|
||||||
|
let isRemux = /remux/i.test(fileName);
|
||||||
|
let isHEVC = (codec === 'hevc' || codec === 'h265');
|
||||||
|
let isAV1 = (codec === 'av1');
|
||||||
|
// Bei unbekannter Bitrate NICHT ablehnen: ein 4K-HEVC-Remux ist per Definition hochbitratig.
|
||||||
|
let brKnown = bitrateMbps > 0;
|
||||||
|
let highBR = brKnown ? (bitrateMbps >= MinSourceMbps) : true;
|
||||||
|
|
||||||
|
Logger.ILog('Datei: ' + fileName);
|
||||||
|
Logger.ILog('Video: codec=' + codec + ' width=' + width + ' bitrate=' +
|
||||||
|
(brKnown ? bitrateMbps.toFixed(1) + ' Mbit/s' : 'unbekannt'));
|
||||||
|
Logger.ILog('Checks: 4K=' + is4K + ' Remux=' + isRemux + ' HEVC=' + isHEVC +
|
||||||
|
' >=' + MinSourceMbps + 'Mbit=' + highBR + (brKnown ? '' : ' (Bitrate unbekannt->Remux gilt als HB)'));
|
||||||
|
|
||||||
|
if (isAV1) { Logger.ILog('Bereits AV1 - kein Re-Encode.'); return 2; }
|
||||||
|
if (!is4K) { Logger.ILog('Nicht 4K (<' + MinWidth + 'px).'); return 2; }
|
||||||
|
if (!isRemux) { Logger.ILog('Kein "Remux" im Dateinamen.'); return 2; }
|
||||||
|
if (!isHEVC) { Logger.ILog('Codec ist nicht HEVC/H265.'); return 2; }
|
||||||
|
if (!highBR) { Logger.ILog('Bitrate < ' + MinSourceMbps + ' Mbit/s - lohnt nicht.'); return 2; }
|
||||||
|
|
||||||
|
Logger.ILog('-> 4K Remux HEVC Kandidat fuer AV1 Encode');
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue