From 5ac9c85c06c20e41b2d8088b58d2ab360132ff4d Mon Sep 17 00:00:00 2001 From: Migz93 <33037112+Migz93@users.noreply.github.com> Date: Sun, 9 Feb 2020 21:58:05 +0000 Subject: [PATCH 1/2] Migz Plugin: Bug Fix Resolve bug with Migz1FFMPEG where bitrate transcode targets were always displayed, even if the file already meets h265/container and isn't used. --- Community/Tdarr_Plugin_MC93_Migz1FFMPEG.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Community/Tdarr_Plugin_MC93_Migz1FFMPEG.js b/Community/Tdarr_Plugin_MC93_Migz1FFMPEG.js index 381d69c..6cdd9ac 100644 --- a/Community/Tdarr_Plugin_MC93_Migz1FFMPEG.js +++ b/Community/Tdarr_Plugin_MC93_Migz1FFMPEG.js @@ -65,9 +65,6 @@ function plugin(file, librarySettings, inputs) { response.infoLog += "☒Target bitrate could not be calculated. Skipping this plugin. \n" return response } - - bitrateSettings = `-b:v ${targetBitrate}k -minrate ${minimumBitrate}k -maxrate ${maximumBitrate}k` - response.infoLog += `Container for output selected as ${inputs.container}. \n Current bitrate = ${~~(file.file_size / (duration * 0.0075))} \n Bitrate settings: \nTarget = ${targetBitrate} \nMinimum = ${minimumBitrate} \nMaximum = ${maximumBitrate} \n` if (file.ffProbeData.streams[0].codec_name == 'hevc' && file.container == inputs.container) { response.processFile = false @@ -81,6 +78,9 @@ function plugin(file, librarySettings, inputs) { response.processFile = true; return response } + + bitrateSettings = `-b:v ${targetBitrate}k -minrate ${minimumBitrate}k -maxrate ${maximumBitrate}k` + response.infoLog += `Container for output selected as ${inputs.container}. \n Current bitrate = ${~~(file.file_size / (duration * 0.0075))} \n Bitrate settings: \nTarget = ${targetBitrate} \nMinimum = ${minimumBitrate} \nMaximum = ${maximumBitrate} \n` //codec will be checked so it can be transcoded correctly if (file.video_codec_name == 'h263') { From a45de61b72b3466f65216afd016ab350bfe8bb55 Mon Sep 17 00:00:00 2001 From: Jack Dallas <3620144+JackDallas@users.noreply.github.com> Date: Wed, 12 Feb 2020 13:55:08 +0000 Subject: [PATCH 2/2] Initial Commit of Generic FFmpeg preset plugin h264/mp4 --- ...gin_da11_Dallas_FFmpeg_Presets_H264_MP4.js | 193 ++++++++++++++++++ 1 file changed, 193 insertions(+) create mode 100644 Community/Tdarr_Plugin_da11_Dallas_FFmpeg_Presets_H264_MP4.js diff --git a/Community/Tdarr_Plugin_da11_Dallas_FFmpeg_Presets_H264_MP4.js b/Community/Tdarr_Plugin_da11_Dallas_FFmpeg_Presets_H264_MP4.js new file mode 100644 index 0000000..12f64d8 --- /dev/null +++ b/Community/Tdarr_Plugin_da11_Dallas_FFmpeg_Presets_H264_MP4.js @@ -0,0 +1,193 @@ +function details() { + return { + id: "Tdarr_Plugin_da11_Dallas_FFmpeg_Presets_H264_MP4", + Stage: "Pre-processing", + Name: "Dallas FFmpeg h264 mp4. Video: h264/mp4, Subs: Convert to mov_text or drop, Audio: aac", + Type: "Video", + Description: `This plugin transcodes into H264 with an MP4 container using the FFmpeg preset you select (slow,medium,fast,veryfast). It maintains all compatible subtitles and audio tracks. \n\n`, + Version: "1.00", + Link: "https://github.com/JackDallas/Tdarr_Plugins/blob/master/Community/Tdarr_Plugin_da11_Dallas_FFmpeg_Presets_H264_MP4.js", + Inputs: [ + { + name: 'FFmpeg_preset', + tooltip: `Select the FFmpeg preset you wish to use,(slow,medium,fast,veryfast). + + \\nExample:\\n + slow + + \\nExample:\\n + medium + + \\nExample:\\n + fast + + \\nExample:\\n + veryfast` + } + ] + }; +} + +const presets = [ + "slow", "medium", "fast", "veryfast" +]; + +// Normalizes the preset or if invalid returns null +function getPreset(preset) { + if (!preset) + return null; + + preset = preset.toLowerCase(); + // Strip Spaces + preset = preset.replace(/\s+/g, ''); + + if (presets.includes(preset)) { + return preset; + } + + return null; +} + +const GOOD = true; +const BAD = false; + +function plugin(file, librarySettings, inputs) { + var response = { + processFile: false, + preset: '', + container: '.mp4', + handBrakeMode: false, + FFmpegMode: false, + reQueueAfter: false, + infoLog: '', + addInfo(status, info) { + this.infoLog += (status ? "☑" : "☒") + " " + info + "\n"; + } + } + + // Check the file is a video + if (file.fileMedium !== "video") { + console.log("File is not video"); + response.addInfo(BAD, `File is not video`); + response.processFile = false; + return response; + } + + // Get and check the preset + let preset = getPreset(inputs.FFmpeg_preset); + + if (preset === null) { + response.addInfo(BAD, `Invalid Preset, \"${inputs.FFmpeg_preset}\" please select from (slow,medium,fast,veryfast)`); + + throw `Error: Invalid Preset, \"${inputs.FFmpeg_preset}\" please select from (slow,medium,fast,veryfast) \n` + } + + var jsonString = JSON.stringify(file) + + var hasSubs = false; + var hasBadSubs = false; + var subType = "-c:s mov_text"; + var subMap = ""; + + for (var i = 0; i < file.ffProbeData.streams.length; i++) { + try { + let streamData = file.ffProbeData.streams[i]; + if (streamData.codec_type.toLowerCase() == "subtitle") { + if (streamData.codec_name === "hdmv_pgs_subtitle" || streamData.codec_name === "dvd_subtitle") { + hasBadSubs = true; + // Drop incompatible subs + subMap += " -map -0:" + streamData.index + " "; + } else if (streamData.codec_name != "mov_text") { + hasSubs = true + // Keep compatible subs + subMap += " -map 0:" + streamData.index + " "; + } + } + } catch (err) { + console.log("Error reading stream: " + JSON.stringify(err)); + } + } + + if (hasBadSubs) + response.addInfo(BAD, "File contains unsupported sub(s), dropping these!"); + + if (file.ffProbeData.streams[0].codec_name != 'h264') { + response.addInfo(BAD, "File is not in h264!"); + response.preset = ', -map_metadata -1 -map 0:v ' + subMap + ' -map 0:a -c:v libx264 -preset medium -c:a aac ' + subType; + response.reQueueAfter = true; + response.processFile = true; + response.FFmpegMode = true; + return response; + } else { + response.addInfo(GOOD, "File is already in h264!"); + } + + if ((file.meta.Title != undefined) && !jsonString.includes("aac") && hasSubs) { + response.addInfo(BAD, "File has title metadata and no aac and subs"); + response.preset = ', -map_metadata -1 -map 0:v ' + subMap + ' -map 0:a -c:v copy -c:a aac ' + subType; + response.reQueueAfter = true; + response.processFile = true; + response.FFmpegMode = true; + return response + } + + if (!jsonString.includes("aac") && hasSubs) { + response.addInfo(BAD, "File has no aac track and has subs"); + response.preset = ', -map 0:v ' + subMap + ' -map 0:a -c:v copy -c:a aac ' + subType; + response.reQueueAfter = true; + response.processFile = true; + response.FFmpegMode = true; + return response; + } + + if (file.meta.Title != undefined && hasSubs) { + response.addInfo(BAD, "File has title and has subs"); + response.preset = ', -map_metadata -1 -map 0:v ' + subMap + ' -map 0:a -c:v copy -c:a copy ' + subType; + response.reQueueAfter = true; + response.processFile = true; + response.FFmpegMode = true; + return response; + } + + if (file.meta.Title != undefined) { + response.addInfo(BAD, "File has title metadata"); + response.preset = ', -map_metadata -1 -map 0:v ' + subMap + ' -map 0:a -c:v copy -c:a copy ' + subType; + response.reQueueAfter = true; + response.processFile = true; + response.FFmpegMode = true; + return response; + } else { + response.addInfo(GOOD, "File has no title metadata"); + } + + if (!jsonString.includes("aac")) { + response.addInfo(BAD, "File has no aac track"); + response.preset = ', -map 0:v ' + subMap + ' -map 0:a -c:v copy -c:a aac ' + subType; + response.reQueueAfter = true; + response.processFile = true; + response.FFmpegMode = true; + return response; + } else { + response.addInfo(GOOD, "File has aac track"); + } + + if (hasSubs) { + if (hasBadSubs) { + response.addInfo(BAD, "File has incompatible subs, dropping these..."); + } else { + response.addInfo(BAD, "File has compatible subs, copying..."); + } + response.preset = ', -map 0:v ' + subMap + ' -map 0:a -c:v copy -c:a copy ' + subType; + response.processFile = true; + response.FFmpegMode = true + return response + } else { + response.addInfo(GOOD, "File has no/compatible subs"); + } + + response.addInfo(GOOD, "File meets conditions!"); + return response +} + +module.exports.details = details; +module.exports.plugin = plugin;