/* eslint max-len: 0, no-plusplus: ["error", { "allowForLoopAfterthoughts": true }] */ const details = () => ({ id: 'Tdarr_Plugin_gabehf_Make_Default_Tracks_First', Stage: 'Pre-processing', Name: 'Make Default Tracks First', Type: 'Video', Operation: 'Transcode', Description: 'Re-orders streams to move default audio and subtitle tracks to be first. \\n', Version: '1.0', Tags: 'pre-processing,ffmpeg', Inputs: [], }); // eslint-disable-next-line @typescript-eslint/no-unused-vars const plugin = (file, librarySettings, inputs, otherArguments) => { const lib = require('../methods/lib')(); // eslint-disable-next-line @typescript-eslint/no-unused-vars,no-param-reassign inputs = lib.loadDefaultValues(inputs, details); const response = { processFile: false, preset: '', container: `.${file.container}`, handBrakeMode: false, FFmpegMode: true, reQueueAfter: false, infoLog: '', }; // Check if file is a video. If it isn't then exit plugin. if (file.fileMedium !== 'video') { // eslint-disable-next-line no-console console.log('File is not video'); response.infoLog += '☒File is not video \n'; response.processFile = false; return response; } // Set up required variables. let ffmpegCommandInsert = ''; let audioIdx = 0; let defaultAudioIdx = 0; let subtitleIdx = 0; let defaultSubtitleIdx = 0; let audioFfmpegInsert = "" let subtitleFfmpegInsert = "" let convert = false; let processAudio = false; let processSubtitles = false; let hasDefaultSubTrack = false; let hasDefaultAudioTrack = false; let firstAudioTrackIsDefault = false; let firstSubTrackIsDefault = false; // [false, true, true] for (let i = 0; i < file.ffProbeData.streams.length; i++) { try { if (file.ffProbeData.streams[i].codec_type.toLowerCase() === 'audio') { if (file.ffProbeData.streams[i].disposition.default === 1) { hasDefaultAudioTrack = true; if (audioIdx === 0) { firstAudioTrackIsDefault = true response.infoLog += "☒Default audio stream is already first \n" audioFfmpegInsert += "-map 0:a " } else if (!firstAudioTrackIsDefault) { convert = true; processAudio = true; defaultAudioIdx = audioIdx; audioFfmpegInsert += `-map 0:a:${defaultAudioIdx} ` response.infoLog += `☒Moving default audio stream with index ${audioIdx} to first \n` } } audioIdx += 1; } else if (file.ffProbeData.streams[i].codec_type.toLowerCase() === 'subtitle') { if (file.ffProbeData.streams[i].disposition.default === 1) { hasDefaultSubTrack = true; if (subtitleIdx === 0) { firstSubTrackIsDefault = true response.infoLog += "☒Default subtitle stream is already first \n" subtitleFfmpegInsert += "-map 0:s " } else if (!firstSubTrackIsDefault) { convert = true; processSubtitles = true; defaultSubtitleIdx = subtitleIdx; subtitleFfmpegInsert += `-map 0:s:${defaultSubtitleIdx} ` response.infoLog += `☒Moving default subtitle stream with index ${subtitleIdx} to first \n` } } subtitleIdx += 1; } } catch (err) { // Error } } // if there are no default sub tracks, just copy them all if (!hasDefaultSubTrack) { subtitleFfmpegInsert += "-map 0:s? " } // if there are no default audio tracks, just copy them all if (!hasDefaultAudioTrack) { audioFfmpegInsert += "-map 0:a? " } if (convert) { if (processAudio) { for (let i = 0; i < audioIdx; i++) { if (i == defaultAudioIdx) { continue; } else { audioFfmpegInsert += `-map 0:a:${i} ` } } } if (processSubtitles) { for (let i = 0; i < subtitleIdx; i++) { if (i == defaultSubtitleIdx) { continue; } else { subtitleFfmpegInsert += `-map 0:s:${i} ` } } } ffmpegCommandInsert += audioFfmpegInsert; ffmpegCommandInsert += subtitleFfmpegInsert; } // Convert file if convert variable is set to true. if (convert === true) { response.processFile = true; response.preset = `, -map 0:v ${ffmpegCommandInsert}-map 0:t? -default_mode passthrough -c copy -max_muxing_queue_size 9999`; response.container = `.${file.container}`; response.reQueueAfter = true; } else { response.processFile = false; response.infoLog += "☑File doesn't contain tracks that require modification.\n"; } return response; }; module.exports.details = details; module.exports.plugin = plugin;