const details = () => ({ id: 'Tdarr_Plugin_MM1_MrMeeb_Extract_Subs', Stage: 'Pre-processing', Name: 'MrMeeb Extract Subtitles', Type: 'Subtitle', Operation: 'Transcode', Description: 'Automatically extracts SRT subtitles to external files and removes the embedded ones. Created to fix a bug where Infuse cannot auto-select embedded forced subtitles', Version: '0.1', Tags: 'pre-processing', Inputs: [], }); // eslint-disable-next-line no-unused-vars const plugin = (file, librarySettings, inputs, otherArguments) => { const lib = require('../methods/lib')(); // load default plugin inputs inputs = lib.loadDefaultValues(inputs, details); // Load response object const response = { processFile: false, // If set to false, the file will be skipped. Set to true to have the file transcoded. preset: '', // HandBrake/FFmpeg CLI arguments you'd like to use. // For FFmpeg, the input arguments come first followed by , followed by the output argument. // Examples // HandBrake // '-Z "Very Fast 1080p30"' // FFmpeg // '-sn -map_metadata -1 -c:v copy -c:a copy' container: '.mp4', // The container of the transcoded output file. handBrakeMode: false, // Set whether to use HandBrake or FFmpeg for transcoding FFmpegMode: false, infoLog: '', // This will be shown when the user clicks the 'i' (info) button on a file in the output queue if // it has been skipped. // Give reasons why it has been skipped ('File has no title metadata, File meets conditions!') // Optional (include together) //file, //removeFromDB: false, // Tell Tdarr to remove file from database if true //updateDB: false, // Change file object above and update database if true }; // Required global variables for functions let ffmpegSubs = ''; // Defining functions const removeMKV = (filename) => { const re = filename.replace(/\.mkv/g, ''); return re } // Function variables let subIdx = -1; // The stream index of the current subtitle stream, relative to all subtitle steams console.log(` === Running Extract Subs function === `) response.jobLog += `Hello!` // Identify all subtitles for (let i = 0; i < file.ffProbeData.streams.length; i ++) { // Work with subtitle streams only if ( file.ffProbeData.streams[i].codec_type.toLowerCase() === 'subtitle' && file.ffProbeData.streams[i].codec_name.toLowerCase() === 'subrip' ) { // Set language to variable let subLang = file.ffProbeData.streams[i].tags.language.toLowerCase() let subName = removeMKV(otherArguments.originalLibraryFile.meta.FileName) // Keep track of subtitle stream relative numbers try { if ( file.ffProbeData.streams[i].codec_type.toLowerCase() === 'subtitle' ) { subIdx++; } } catch (err) {} // Extract forced and SDH subtitles if ( (file.ffProbeData.streams[i].disposition.hearing_impaired == 1 && file.ffProbeData.streams[i].disposition.forced == 1) || (file.ffProbeData.streams[i].tags.title != undefined && file.ffProbeData.streams[i].tags.title.toLowerCase().includes("sdh") && file.ffProbeData.streams[i].disposition.forced == 1) ) { console.log(`Stream ${i} (subtitle stream ${subIdx}) is SDH and forced.`) response.infoLog += `Stream ${i} (subtitle stream ${subIdx}) is SDH and forced. \n` ffmpegSubs += ` -map 0:s:${subIdx} -c copy "${otherArguments.originalLibraryFile.meta.Directory}/${subName}-${subIdx}.${subLang}.sdh.forced.srt"` } // Extract SDH subtitles else if ( file.ffProbeData.streams[i].disposition.hearing_impaired == 1 || (file.ffProbeData.streams[i].tags.title != undefined && file.ffProbeData.streams[i].tags.title.toLowerCase().includes("sdh")) ) { console.log(`Stream ${i} (subtitle stream ${subIdx}) is SDH.`) response.infoLog += `Stream ${i} (subtitle stream ${subIdx}) is SDH. \n` ffmpegSubs += ` -map 0:s:${subIdx} -c copy "${otherArguments.originalLibraryFile.meta.Directory}/${subName}-${subIdx}.${subLang}.sdh.srt"` } // Extract forced subtitles else if ( file.ffProbeData.streams[i].disposition.forced == 1 ) { console.log(`Stream ${i} (subtitle stream ${subIdx}) is forced.`) response.infoLog += `Stream ${i} (subtitle stream ${subIdx}) is forced. \n` ffmpegSubs += ` -map 0:s:${subIdx} -c copy "${otherArguments.originalLibraryFile.meta.Directory}/${subName}-${subIdx}.${subLang}.forced.srt"` } // Extract forced and SDH subtitles else { console.log(`Stream ${i} (subtitle stream ${subIdx}) is standard.`) response.infoLog += `Stream ${i} (subtitle stream ${subIdx}) is standard. \n` ffmpegSubs += ` -map 0:s:${subIdx} -c copy "${otherArguments.originalLibraryFile.meta.Directory}/${subName}-${subIdx}.${subLang}.srt"` }; } // If subtitles aren't in SRT format else if (file.ffProbeData.streams[i].codec_type.toLowerCase() === 'subtitle') { subIdx++; console.log(`Stream ${i} (subtitle stream ${subIdx}) is a subtitle but not SRT.`) response.infoLog += `Stream ${i} (subtitle stream ${subIdx}) is a subtitle but not SRT. \n` } } // If no subs if (subIdx == -1) { console.log('No SRT subtitles found to extract. No action needed.') response.infoLog += `No SRT subtitles found to extract. No action needed. \n` } if (ffmpegSubs.length > 0) { let subName = removeMKV(otherArguments.originalLibraryFile.meta.FileName) response.infoLog += '☒ Changes are required! \n Extracting SRT files'; require("child_process").execSync(`rm -rf "${otherArguments.originalLibraryFile.meta.Directory}/${subName}"*.srt`) response.FFmpegMode = true; response.container = `.${file.container}`; response.preset = `,${ffmpegSubs} -map 0:v? -map 0:a? -map 0:d? -c copy -max_muxing_queue_size 9999`; console.log(response.preset) response.processFile = true; return response; } if (ffmpegSubs.length == 0) { response.infoLog += '☑ No changes are required \n'; response.processFile = false; return response; } }; module.exports.details = details; module.exports.plugin = plugin;