'use strict'; const path = require('path'); const fs = require('fs'); const { copyWithProgress } = require('../../../../FlowHelpers/1.0.0/copyWithProgress'); /* eslint-disable no-param-reassign */ /** * copyToWorkDir * Copies the source file into the worker's local workDir before processing. * * Use this plugin BEFORE any transcode/extract plugin when: * - The source file lives on a network share / mapped drive * - You want the worker to encode from a local copy to avoid I/O bottleneck * - The network path is slow or unreliable during long encodes * * Flow: * 1. Copies source -> workDir/_old (streamed with real-time progress) * 2. Updates outputFileObj._id to the local copy path * 3. Downstream plugins operate on the local copy * 4. Tdarr replaces the original with the final output via replaceOriginalFile */ const details = () => ({ name: 'Copy Source to Work Dir', description: 'Copies the source file into the worker local workDir using a streamed, verified copy ' + 'with real-time progress, speed, and ETA tracking. Use before transcode plugins ' + 'when the source is on a network share to avoid I/O bottlenecks during encoding.', style: { borderColor: '#607D8B' }, tags: 'utility,copy,progress', isStartPlugin: false, pType: '', requiresVersion: '2.11.01', sidebarPosition: 0, icon: 'faCopy', inputs: [ { label: 'Skip if already local', name: 'skipIfLocal', type: 'boolean', defaultValue: 'true', inputUI: { type: 'dropdown', options: ['true', 'false'], }, tooltip: 'If true, skip the copy when the source file is already inside workDir ' + 'or on the same drive as workDir (avoids double-copy on mapped nodes).', }, ], outputs: [ { number: 1, tooltip: 'File is ready in workDir — continue to next plugin' }, ], }); const plugin = async (args) => { const { jobLog, inputFileObj, variables, workDir, updateWorker } = args; const inputFile = inputFileObj._id; const ext = path.extname(inputFile); const baseName = path.basename(inputFile, ext); const localCopy = path.join(workDir, `${baseName}_old${ext}`); const skipIfLocal = (args.inputs.skipIfLocal || 'true') === 'true'; jobLog(`[copyToWorkDir] Source : ${inputFile}\n`); jobLog(`[copyToWorkDir] WorkDir: ${workDir}\n`); // Skip if source file is already inside workDir const relativeInput = path.relative(path.resolve(workDir), path.resolve(inputFile)); if ( skipIfLocal && relativeInput !== '..' && !relativeInput.startsWith(`..${path.sep}`) && !path.isAbsolute(relativeInput) ) { jobLog('[copyToWorkDir] Source file is already inside workDir — skipping copy.\n'); return { outputNumber: 1, outputFileObj: inputFileObj, variables }; } if (!fs.existsSync(inputFile)) { throw new Error(`[copyToWorkDir] Source file not found: ${inputFile}`); } // Preserve original library paths for downstream plugins if (!variables.originalLibraryFile) { variables.originalLibraryFile = inputFile; variables.originalLibraryDir = path.dirname(inputFile); } variables.workDirSourceBaseName = baseName; variables.workDirCopyApplied = 'true'; jobLog(`[copyToWorkDir] Copying ${inputFile} to ${localCopy}\n`); await copyWithProgress({ source: inputFile, destination: localCopy, jobLog, updateWorker, updateProgress: args.updateProgress, label: 'copyToWorkDir', }); return { outputNumber: 1, outputFileObj: { ...inputFileObj, _id: localCopy }, variables, }; }; module.exports.details = details; module.exports.plugin = plugin;