mirror of
https://github.com/gabehf/Tdarr_Plugins.git
synced 2026-03-14 01:36:08 -07:00
Merge branch 'master' into pr/694
This commit is contained in:
commit
7321a63b4a
56 changed files with 1543 additions and 152 deletions
|
|
@ -124,7 +124,7 @@ const plugin = (args: IpluginInputArgs): IpluginOutputArgs => {
|
|||
'mpeg',
|
||||
].includes(container)
|
||||
) {
|
||||
args.variables.ffmpegCommand.overallOuputArguments.push('-fflags', '+genpts');
|
||||
args.variables.ffmpegCommand.overallInputArguments.push('-fflags', '+genpts');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -140,6 +140,7 @@ const details = (): IpluginDetails => ({
|
|||
options: [
|
||||
'auto',
|
||||
'nvenc',
|
||||
'rkmpp',
|
||||
'qsv',
|
||||
'vaapi',
|
||||
'videotoolbox',
|
||||
|
|
|
|||
|
|
@ -10,7 +10,13 @@ import { getFileAbosluteDir } from '../../../../FlowHelpers/1.0.0/fileUtils';
|
|||
/* eslint no-plusplus: ["error", { "allowForLoopAfterthoughts": true }] */
|
||||
const details = (): IpluginDetails => ({
|
||||
name: 'Delete File',
|
||||
description: 'Delete the working file or original file.',
|
||||
description: `
|
||||
Delete the working file or original file.
|
||||
You don't need to use this plugin to clean up files in the cache, Tdarr will do this automatically after the flow.
|
||||
To manually clear the cache, use the 'Clear Cache' flow plugin.
|
||||
If the working file is deleted, the plugin after this one should load a valid working file,
|
||||
such as 'Set Original File' to load the original file, else subsequent plugins will error.
|
||||
`,
|
||||
style: {
|
||||
borderColor: 'red',
|
||||
},
|
||||
|
|
@ -35,6 +41,32 @@ const details = (): IpluginDetails => ({
|
|||
},
|
||||
tooltip: 'Specify the file to delete',
|
||||
},
|
||||
{
|
||||
label: 'Delete Working File If It\'s The Original File',
|
||||
name: 'deleteWorkingFileIfOriginal',
|
||||
type: 'boolean',
|
||||
defaultValue: 'true',
|
||||
inputUI: {
|
||||
type: 'switch',
|
||||
displayConditions: {
|
||||
logic: 'AND',
|
||||
sets: [
|
||||
{
|
||||
logic: 'AND',
|
||||
inputs: [
|
||||
{
|
||||
name: 'fileToDelete',
|
||||
value: 'workingFile',
|
||||
condition: '===',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
tooltip: 'If the option above is set to delete the working file,'
|
||||
+ ' and the working file is the original file, delete the file.',
|
||||
},
|
||||
{
|
||||
label: 'Delete Parent Folder If Empty',
|
||||
name: 'deleteParentFolderIfEmpty',
|
||||
|
|
@ -61,11 +93,29 @@ const plugin = async (args: IpluginInputArgs): Promise<IpluginOutputArgs> => {
|
|||
args.inputs = lib.loadDefaultValues(args.inputs, details);
|
||||
|
||||
const fileToDelete = String(args.inputs.fileToDelete);
|
||||
const { deleteParentFolderIfEmpty } = args.inputs;
|
||||
const {
|
||||
deleteParentFolderIfEmpty,
|
||||
deleteWorkingFileIfOriginal,
|
||||
} = args.inputs;
|
||||
|
||||
if (fileToDelete === 'workingFile') {
|
||||
args.jobLog(`Deleting working file ${args.inputFileObj._id}`);
|
||||
await fsp.unlink(args.inputFileObj._id);
|
||||
const workingFileIsOriginal = args.originalLibraryFile._id === args.inputFileObj._id;
|
||||
|
||||
if (workingFileIsOriginal) {
|
||||
args.jobLog('Working file is the original file!');
|
||||
} else {
|
||||
args.jobLog('Working file is not the original file!');
|
||||
}
|
||||
|
||||
if (
|
||||
(workingFileIsOriginal && deleteWorkingFileIfOriginal)
|
||||
|| !workingFileIsOriginal
|
||||
) {
|
||||
args.jobLog(`Deleting working file ${args.inputFileObj._id}`);
|
||||
await fsp.unlink(args.inputFileObj._id);
|
||||
} else {
|
||||
args.jobLog('Skipping delete of working file because it is the original file');
|
||||
}
|
||||
} else if (fileToDelete === 'originalFile') {
|
||||
args.jobLog(`Deleting original file ${args.originalLibraryFile._id}`);
|
||||
await fsp.unlink(args.originalLibraryFile._id);
|
||||
|
|
|
|||
|
|
@ -13,7 +13,11 @@ import {
|
|||
/* eslint no-plusplus: ["error", { "allowForLoopAfterthoughts": true }] */
|
||||
const details = (): IpluginDetails => ({
|
||||
name: 'Replace Original File',
|
||||
description: 'Replace the original file. If the file hasn\'t changed then no action is taken.',
|
||||
description: `
|
||||
Replace the original file with the 'working' file passed into this plugin.
|
||||
If the file hasn't changed then no action is taken.
|
||||
Note: The 'working' filename and container will replace the original filename and container.
|
||||
`,
|
||||
style: {
|
||||
borderColor: 'green',
|
||||
},
|
||||
|
|
@ -75,10 +79,18 @@ const plugin = async (args: IpluginInputArgs): Promise<IpluginOutputArgs> => {
|
|||
args,
|
||||
});
|
||||
|
||||
const originalFileExists = await fileExists(args.originalLibraryFile._id);
|
||||
const currentFileIsNotOriginal = args.originalLibraryFile._id !== currentPath;
|
||||
|
||||
args.jobLog(JSON.stringify({
|
||||
originalFileExists,
|
||||
currentFileIsNotOriginal,
|
||||
}));
|
||||
|
||||
// delete original file
|
||||
if (
|
||||
await fileExists(args.originalLibraryFile._id)
|
||||
&& args.originalLibraryFile._id !== currentPath
|
||||
originalFileExists
|
||||
&& currentFileIsNotOriginal
|
||||
) {
|
||||
args.jobLog(`Deleting original file:${args.originalLibraryFile._id}`);
|
||||
await fsp.unlink(args.originalLibraryFile._id);
|
||||
|
|
|
|||
|
|
@ -7,8 +7,7 @@ import {
|
|||
/* eslint no-plusplus: ["error", { "allowForLoopAfterthoughts": true }] */
|
||||
const details = ():IpluginDetails => ({
|
||||
name: 'Set Original File',
|
||||
description: 'Set the working file to the original file path at the very start of the flow. '
|
||||
+ 'The original file won\'t be affected by subsequent plugins (E.g. Replace Original File).',
|
||||
description: 'Set the working file to the original file path at the very start of the flow.',
|
||||
style: {
|
||||
borderColor: 'green',
|
||||
},
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ const details = (): IpluginDetails => ({
|
|||
options: [
|
||||
'hevc_nvenc',
|
||||
'hevc_amf',
|
||||
'hevc_rkmpp',
|
||||
'hevc_vaapi',
|
||||
'hevc_qsv',
|
||||
'hevc_videotoolbox',
|
||||
|
|
|
|||
|
|
@ -0,0 +1,125 @@
|
|||
import { promises as fsp } from 'fs';
|
||||
import {
|
||||
IpluginDetails,
|
||||
IpluginInputArgs,
|
||||
IpluginOutputArgs,
|
||||
} from '../../../../FlowHelpers/1.0.0/interfaces/interfaces';
|
||||
import normJoinPath from '../../../../FlowHelpers/1.0.0/normJoinPath';
|
||||
|
||||
const helperText = `
|
||||
jobCache: Clears all other files in this job's cache folder (which is a subfolder of the library cache).
|
||||
libraryCache: Clears all other files in the library cache.
|
||||
`;
|
||||
|
||||
/* eslint no-plusplus: ["error", { "allowForLoopAfterthoughts": true }] */
|
||||
const details = (): IpluginDetails => ({
|
||||
name: 'Clear Cache',
|
||||
description: `
|
||||
This plugin allows you to clear various cache folders, keeping only the current 'working' file.
|
||||
${helperText}
|
||||
|
||||
`,
|
||||
style: {
|
||||
borderColor: 'red',
|
||||
},
|
||||
tags: '',
|
||||
isStartPlugin: false,
|
||||
pType: '',
|
||||
requiresVersion: '2.11.01',
|
||||
sidebarPosition: -1,
|
||||
icon: 'faTrash',
|
||||
inputs: [
|
||||
{
|
||||
label: 'Cache To Clear',
|
||||
name: 'cacheToClear',
|
||||
type: 'string',
|
||||
defaultValue: 'jobCache',
|
||||
inputUI: {
|
||||
type: 'dropdown',
|
||||
options: [
|
||||
'jobCache',
|
||||
'libraryCache',
|
||||
],
|
||||
},
|
||||
tooltip: `Specify which cache to clear
|
||||
${helperText}
|
||||
`,
|
||||
},
|
||||
],
|
||||
outputs: [
|
||||
{
|
||||
number: 1,
|
||||
tooltip: 'Continue to next plugin',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const plugin = async (args: IpluginInputArgs): Promise<IpluginOutputArgs> => {
|
||||
const lib = require('../../../../../methods/lib')();
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars,no-param-reassign
|
||||
args.inputs = lib.loadDefaultValues(args.inputs, details);
|
||||
|
||||
const { cacheToClear } = args.inputs;
|
||||
|
||||
const currentFile = args.inputFileObj._id;
|
||||
const jobCacheDir = args.workDir;
|
||||
const libraryCacheDir = args.librarySettings.cache;
|
||||
|
||||
let folderToClear = '';
|
||||
|
||||
if (cacheToClear === 'jobCache') {
|
||||
folderToClear = jobCacheDir;
|
||||
} else if (cacheToClear === 'libraryCache') {
|
||||
folderToClear = libraryCacheDir;
|
||||
}
|
||||
|
||||
args.jobLog(`Clearing ${cacheToClear} folder: "${folderToClear}"`);
|
||||
args.jobLog(`Keeping current file: "${currentFile}"`);
|
||||
|
||||
const traverseFolder = async (dir:string) => {
|
||||
const filesInDir = (await fsp.readdir(dir)).map((file) => normJoinPath({
|
||||
upath: args.deps.upath,
|
||||
paths: [
|
||||
dir,
|
||||
file,
|
||||
],
|
||||
}));
|
||||
|
||||
for (let i = 0; i < filesInDir.length; i += 1) {
|
||||
const file = filesInDir[i];
|
||||
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
const stat = await fsp.stat(file);
|
||||
|
||||
if (stat.isDirectory()) {
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
await traverseFolder(file);
|
||||
} else if (
|
||||
file !== currentFile
|
||||
// prevent deleting non Tdarr cache files
|
||||
&& file.includes('tdarr-workDir2')
|
||||
) {
|
||||
args.jobLog(`Deleting "${file}"`);
|
||||
try {
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
await fsp.unlink(file);
|
||||
} catch (err) {
|
||||
args.jobLog(`File delete error: ${JSON.stringify(err)}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
await traverseFolder(folderToClear);
|
||||
|
||||
return {
|
||||
outputFileObj: args.inputFileObj,
|
||||
outputNumber: 1,
|
||||
variables: args.variables,
|
||||
};
|
||||
};
|
||||
export {
|
||||
details,
|
||||
plugin,
|
||||
};
|
||||
|
|
@ -0,0 +1,105 @@
|
|||
/* eslint-disable max-len */
|
||||
|
||||
import { promises as fsp } from 'fs';
|
||||
import { getPluginWorkDir } from '../../../../FlowHelpers/1.0.0/fileUtils';
|
||||
import {
|
||||
IpluginDetails,
|
||||
IpluginInputArgs,
|
||||
IpluginOutputArgs,
|
||||
} from '../../../../FlowHelpers/1.0.0/interfaces/interfaces';
|
||||
|
||||
/* eslint no-plusplus: ["error", { "allowForLoopAfterthoughts": true }] */
|
||||
const details = (): IpluginDetails => ({
|
||||
name: 'Custom JS Function',
|
||||
description: 'Write a custom function in JS to run with up to 4 outputs',
|
||||
style: {
|
||||
borderColor: 'green',
|
||||
},
|
||||
tags: '',
|
||||
isStartPlugin: false,
|
||||
pType: '',
|
||||
requiresVersion: '2.11.01',
|
||||
sidebarPosition: -1,
|
||||
icon: 'faArrowRight',
|
||||
inputs: [
|
||||
{
|
||||
label: 'JS Code',
|
||||
name: 'code',
|
||||
type: 'string',
|
||||
defaultValue: `
|
||||
module.exports = async (args) => {
|
||||
|
||||
// see args object data here https://github.com/HaveAGitGat/Tdarr_Plugins/blob/master/FlowPluginsTs/FlowHelpers/1.0.0/interfaces/interfaces.ts
|
||||
// example setting flow variable: https://github.com/HaveAGitGat/Tdarr/issues/1147#issuecomment-2593348443
|
||||
// example reading ffmpeg metadata: https://github.com/HaveAGitGat/Tdarr_Plugins/issues/737#issuecomment-2581536112
|
||||
// example setting working file as previous working file: https://github.com/HaveAGitGat/Tdarr/issues/1106#issuecomment-2622177459
|
||||
|
||||
// some example file data:
|
||||
console.log(args.inputFileObj._id)
|
||||
console.log(args.inputFileObj.file_size)
|
||||
console.log(args.inputFileObj.ffProbeData.streams[0].codec_name)
|
||||
console.log(args.inputFileObj.mediaInfo.track[0].BitRate)
|
||||
|
||||
// access global variable:
|
||||
console.log(args.userVariables.global.test)
|
||||
// access library variable:
|
||||
console.log(args.userVariables.library.test)
|
||||
|
||||
|
||||
|
||||
// do something here
|
||||
|
||||
return {
|
||||
outputFileObj: args.inputFileObj,
|
||||
outputNumber: 1,
|
||||
variables: args.variables,
|
||||
};
|
||||
}
|
||||
`,
|
||||
inputUI: {
|
||||
type: 'textarea',
|
||||
style: {
|
||||
height: '200px',
|
||||
},
|
||||
},
|
||||
tooltip: 'Write your custom function here',
|
||||
},
|
||||
],
|
||||
outputs: [
|
||||
{
|
||||
number: 1,
|
||||
tooltip: 'Continue to output 1',
|
||||
},
|
||||
{
|
||||
number: 2,
|
||||
tooltip: 'Continue to output 2',
|
||||
},
|
||||
{
|
||||
number: 3,
|
||||
tooltip: 'Continue to output 3',
|
||||
},
|
||||
{
|
||||
number: 4,
|
||||
tooltip: 'Continue to output 4',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const plugin = async (args: IpluginInputArgs): Promise<IpluginOutputArgs> => {
|
||||
const lib = require('../../../../../methods/lib')();
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars,no-param-reassign
|
||||
args.inputs = lib.loadDefaultValues(args.inputs, details);
|
||||
const code = String(args.inputs.code);
|
||||
|
||||
const outputFilePath = `${getPluginWorkDir(args)}/script.js`;
|
||||
await fsp.writeFile(outputFilePath, code);
|
||||
// eslint-disable-next-line import/no-dynamic-require
|
||||
const func = require(outputFilePath);
|
||||
const response = await func(args);
|
||||
return response;
|
||||
};
|
||||
export {
|
||||
details,
|
||||
plugin,
|
||||
};
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
import {
|
||||
IpluginDetails,
|
||||
IpluginInputArgs,
|
||||
IpluginOutputArgs,
|
||||
} from '../../../../FlowHelpers/1.0.0/interfaces/interfaces';
|
||||
|
||||
/* eslint no-plusplus: ["error", { "allowForLoopAfterthoughts": true }] */
|
||||
const details = (): IpluginDetails => ({
|
||||
name: 'Remove From Tdarr',
|
||||
description: `
|
||||
If this plugin is executed, then when the flow ends, the item will be
|
||||
removed from the Tdarr database and won't appear in Transcode Success or Error tables on the 'Tdarr' tab.
|
||||
Use the 'Delete File' plugin if you would like to delete the file from disk.
|
||||
`,
|
||||
style: {
|
||||
borderColor: 'red',
|
||||
},
|
||||
tags: '',
|
||||
isStartPlugin: false,
|
||||
pType: '',
|
||||
requiresVersion: '2.31.01',
|
||||
sidebarPosition: -1,
|
||||
icon: 'faTrash',
|
||||
inputs: [],
|
||||
outputs: [
|
||||
{
|
||||
number: 1,
|
||||
tooltip: 'Continue to next plugin',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const plugin = (args: IpluginInputArgs): IpluginOutputArgs => {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
args.variables.removeFromTdarr = true;
|
||||
|
||||
return {
|
||||
outputFileObj: args.inputFileObj,
|
||||
outputNumber: 1,
|
||||
variables: args.variables,
|
||||
};
|
||||
};
|
||||
export {
|
||||
details,
|
||||
plugin,
|
||||
};
|
||||
|
|
@ -74,6 +74,16 @@ const details = (): IpluginDetails => ({
|
|||
},
|
||||
tooltip: 'Specify request body',
|
||||
},
|
||||
{
|
||||
label: 'Log Response Body',
|
||||
name: 'logResponseBody',
|
||||
type: 'boolean',
|
||||
defaultValue: 'false',
|
||||
inputUI: {
|
||||
type: 'switch',
|
||||
},
|
||||
tooltip: 'Specify whether to log response body in the job report',
|
||||
},
|
||||
],
|
||||
outputs: [
|
||||
{
|
||||
|
|
@ -93,6 +103,7 @@ const plugin = async (args: IpluginInputArgs): Promise<IpluginOutputArgs> => {
|
|||
const requestUrl = String(args.inputs.requestUrl);
|
||||
const requestHeaders = JSON.parse(String(args.inputs.requestHeaders));
|
||||
const requestBody = JSON.parse(String(args.inputs.requestBody));
|
||||
const { logResponseBody } = args.inputs;
|
||||
|
||||
const requestConfig = {
|
||||
method,
|
||||
|
|
@ -104,6 +115,10 @@ const plugin = async (args: IpluginInputArgs): Promise<IpluginOutputArgs> => {
|
|||
try {
|
||||
const res = await args.deps.axios(requestConfig);
|
||||
args.jobLog(`Web request succeeded: Status Code: ${res.status}`);
|
||||
|
||||
if (logResponseBody) {
|
||||
args.jobLog(`Response Body: ${JSON.stringify(res.data)}`);
|
||||
}
|
||||
} catch (err) {
|
||||
args.jobLog('Web Request Failed');
|
||||
args.jobLog(JSON.stringify(err));
|
||||
|
|
|
|||
284
FlowPluginsTs/CommunityFlowTemplates/tutorials/chapter8.tsx
Normal file
284
FlowPluginsTs/CommunityFlowTemplates/tutorials/chapter8.tsx
Normal file
|
|
@ -0,0 +1,284 @@
|
|||
/* eslint-disable no-template-curly-in-string */
|
||||
/* eslint-disable import/prefer-default-export */
|
||||
|
||||
import { IflowTemplate } from '../../FlowHelpers/1.0.0/interfaces/interfaces';
|
||||
|
||||
const details = () :IflowTemplate => ({
|
||||
"name": "Chapter 8: Unmapped Nodes",
|
||||
"description": "Chapter 8: Unmapped Nodes",
|
||||
"tags": "",
|
||||
"flowPlugins": [
|
||||
{
|
||||
"name": "Tags: Worker Type - Mapped Node",
|
||||
"sourceRepo": "Community",
|
||||
"pluginName": "tagsWorkerType",
|
||||
"version": "1.0.0",
|
||||
"id": "XDkUDTqXV",
|
||||
"position": {
|
||||
"x": 618.728206498488,
|
||||
"y": 797.6991616678526
|
||||
},
|
||||
"fpEnabled": true,
|
||||
"inputsDB": {
|
||||
"requiredNodeTags": "mapped"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Tags: Worker Type - Unmapped Node",
|
||||
"sourceRepo": "Community",
|
||||
"pluginName": "tagsWorkerType",
|
||||
"version": "1.0.0",
|
||||
"id": "Gm1kh8K5w",
|
||||
"position": {
|
||||
"x": 487.23666063579026,
|
||||
"y": 281.79774016757386
|
||||
},
|
||||
"fpEnabled": true,
|
||||
"inputsDB": {
|
||||
"requiredNodeTags": "unmapped"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Input File",
|
||||
"sourceRepo": "Community",
|
||||
"pluginName": "inputFile",
|
||||
"version": "1.0.0",
|
||||
"id": "pE6rU7gkW",
|
||||
"position": {
|
||||
"x": 788.5712895368422,
|
||||
"y": 45.83576905176477
|
||||
},
|
||||
"fpEnabled": true
|
||||
},
|
||||
{
|
||||
"name": "Check if hevc",
|
||||
"sourceRepo": "Community",
|
||||
"pluginName": "checkVideoCodec",
|
||||
"version": "1.0.0",
|
||||
"id": "91b7IrsEc",
|
||||
"position": {
|
||||
"x": 788.2207108267078,
|
||||
"y": 203.7781028159269
|
||||
},
|
||||
"fpEnabled": true
|
||||
},
|
||||
{
|
||||
"name": "Start",
|
||||
"sourceRepo": "Community",
|
||||
"pluginName": "ffmpegCommandStart",
|
||||
"version": "1.0.0",
|
||||
"id": "4Swd6qzvc",
|
||||
"position": {
|
||||
"x": 489.25252076795084,
|
||||
"y": 370.51229288382495
|
||||
},
|
||||
"fpEnabled": true
|
||||
},
|
||||
{
|
||||
"name": "Execute",
|
||||
"sourceRepo": "Community",
|
||||
"pluginName": "ffmpegCommandExecute",
|
||||
"version": "1.0.0",
|
||||
"id": "450g167D8",
|
||||
"position": {
|
||||
"x": 488.72295602997406,
|
||||
"y": 699.5034828311435
|
||||
},
|
||||
"fpEnabled": true
|
||||
},
|
||||
{
|
||||
"name": "Set Video Encoder",
|
||||
"sourceRepo": "Community",
|
||||
"pluginName": "ffmpegCommandSetVideoEncoder",
|
||||
"version": "1.0.0",
|
||||
"id": "8B_6pRd_U",
|
||||
"position": {
|
||||
"x": 488.5270135748424,
|
||||
"y": 477.83202026423606
|
||||
},
|
||||
"fpEnabled": true
|
||||
},
|
||||
{
|
||||
"name": "Replace Original File",
|
||||
"sourceRepo": "Community",
|
||||
"pluginName": "replaceOriginalFile",
|
||||
"version": "1.0.0",
|
||||
"id": "4fkfOyR3l",
|
||||
"position": {
|
||||
"x": 797.2573001129032,
|
||||
"y": 882.7619863463507
|
||||
},
|
||||
"fpEnabled": true
|
||||
},
|
||||
{
|
||||
"name": "Set Container",
|
||||
"sourceRepo": "Community",
|
||||
"pluginName": "ffmpegCommandSetContainer",
|
||||
"version": "1.0.0",
|
||||
"id": "TtKXi3Q7h",
|
||||
"position": {
|
||||
"x": 488.21110165973323,
|
||||
"y": 570.3064821931456
|
||||
},
|
||||
"fpEnabled": true
|
||||
},
|
||||
{
|
||||
"name": "Tags: Worker Type - Mapped Node",
|
||||
"sourceRepo": "Community",
|
||||
"pluginName": "tagsWorkerType",
|
||||
"version": "1.0.0",
|
||||
"id": "7Y_fzVfGm",
|
||||
"position": {
|
||||
"x": 788.7823658666633,
|
||||
"y": 127.15363454994434
|
||||
},
|
||||
"fpEnabled": true,
|
||||
"inputsDB": {
|
||||
"requiredNodeTags": "mapped"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "We will check the file codec on a mapped node. This way bandwidth and time is saved as we don't need to unnecessarily send the whole file to the unmapped node.",
|
||||
"sourceRepo": "Community",
|
||||
"pluginName": "comment",
|
||||
"version": "1.0.0",
|
||||
"id": "6oOV2PLSr",
|
||||
"position": {
|
||||
"x": 958.0256289687773,
|
||||
"y": 129.22000506355067
|
||||
},
|
||||
"fpEnabled": true
|
||||
},
|
||||
{
|
||||
"name": "If the codec is not what we want, we'll require the next transcoding steps to run on an unmapped node. The unmapped node will automatically download the file from the server.",
|
||||
"sourceRepo": "Community",
|
||||
"pluginName": "comment",
|
||||
"version": "1.0.0",
|
||||
"id": "j343VFewY",
|
||||
"position": {
|
||||
"x": 316.4293037925603,
|
||||
"y": 290.6548883625747
|
||||
},
|
||||
"fpEnabled": true
|
||||
},
|
||||
{
|
||||
"name": "After the transcode, we'll run the original file replacement on a mapped node which has access to the server file system. The mapped node will automatically download the working file from the unmapped node.",
|
||||
"sourceRepo": "Community",
|
||||
"pluginName": "comment",
|
||||
"version": "1.0.0",
|
||||
"id": "hVhthld87",
|
||||
"position": {
|
||||
"x": 364.852600714643,
|
||||
"y": 769.3367928955186
|
||||
},
|
||||
"fpEnabled": true
|
||||
},
|
||||
{
|
||||
"name": "Before starting, ensure that in the Node options panel on the Tdarr tab, the mapped node has node tag 'mapped' and the umapped node has node tag 'umapped'.",
|
||||
"sourceRepo": "Community",
|
||||
"pluginName": "comment",
|
||||
"version": "1.0.0",
|
||||
"id": "9sd__MisF",
|
||||
"position": {
|
||||
"x": 791.5682800167409,
|
||||
"y": -93.09360376469954
|
||||
},
|
||||
"fpEnabled": true
|
||||
},
|
||||
{
|
||||
"name": "Unmapped nodes are a new node type for Tdarr Pro members on 2.27.01 and above. More info: https://docs.tdarr.io/docs/nodes/nodes#unmapped",
|
||||
"sourceRepo": "Community",
|
||||
"pluginName": "comment",
|
||||
"version": "1.0.0",
|
||||
"id": "EILF-RWh2",
|
||||
"position": {
|
||||
"x": 791.4236829857584,
|
||||
"y": -209.23734619332546
|
||||
},
|
||||
"fpEnabled": true
|
||||
}
|
||||
],
|
||||
"flowEdges": [
|
||||
{
|
||||
"source": "4Swd6qzvc",
|
||||
"sourceHandle": "1",
|
||||
"target": "8B_6pRd_U",
|
||||
"targetHandle": null,
|
||||
"id": "3Df7Xoy93"
|
||||
},
|
||||
{
|
||||
"source": "8B_6pRd_U",
|
||||
"sourceHandle": "1",
|
||||
"target": "TtKXi3Q7h",
|
||||
"targetHandle": null,
|
||||
"id": "epqtLsPuG"
|
||||
},
|
||||
{
|
||||
"source": "TtKXi3Q7h",
|
||||
"sourceHandle": "1",
|
||||
"target": "450g167D8",
|
||||
"targetHandle": null,
|
||||
"id": "ljOeP0cAZ"
|
||||
},
|
||||
{
|
||||
"source": "450g167D8",
|
||||
"sourceHandle": "1",
|
||||
"target": "XDkUDTqXV",
|
||||
"targetHandle": null,
|
||||
"id": "3412q1wK2"
|
||||
},
|
||||
{
|
||||
"source": "XDkUDTqXV",
|
||||
"sourceHandle": "1",
|
||||
"target": "4fkfOyR3l",
|
||||
"targetHandle": null,
|
||||
"id": "3jQP_egvG"
|
||||
},
|
||||
{
|
||||
"source": "pE6rU7gkW",
|
||||
"sourceHandle": "1",
|
||||
"target": "7Y_fzVfGm",
|
||||
"targetHandle": null,
|
||||
"id": "XHRuig1Dp"
|
||||
},
|
||||
{
|
||||
"source": "7Y_fzVfGm",
|
||||
"sourceHandle": "1",
|
||||
"target": "91b7IrsEc",
|
||||
"targetHandle": null,
|
||||
"id": "_CJ9H5I_X"
|
||||
},
|
||||
{
|
||||
"source": "91b7IrsEc",
|
||||
"sourceHandle": "1",
|
||||
"target": "4fkfOyR3l",
|
||||
"targetHandle": null,
|
||||
"id": "2x5mRYwOU"
|
||||
},
|
||||
{
|
||||
"source": "91b7IrsEc",
|
||||
"sourceHandle": "2",
|
||||
"target": "Gm1kh8K5w",
|
||||
"targetHandle": null,
|
||||
"id": "8eBsa60Xp"
|
||||
},
|
||||
{
|
||||
"source": "Gm1kh8K5w",
|
||||
"sourceHandle": "1",
|
||||
"target": "4Swd6qzvc",
|
||||
"targetHandle": null,
|
||||
"id": "IryDiBCVX"
|
||||
},
|
||||
{
|
||||
"source": "EILF-RWh2",
|
||||
"sourceHandle": "1",
|
||||
"target": "9sd__MisF",
|
||||
"targetHandle": null,
|
||||
"id": "IPiPj8zhv"
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
export {
|
||||
details,
|
||||
};
|
||||
|
|
@ -1,25 +1,52 @@
|
|||
import { getEncoder } from './hardwareUtils';
|
||||
import { getEncoder, IgetEncoder } from './hardwareUtils';
|
||||
|
||||
const run = async () => {
|
||||
const encoderProperties = await getEncoder({
|
||||
targetCodec: 'h264',
|
||||
hardwareEncoding: true,
|
||||
hardwareType: 'auto',
|
||||
// @ts-expect-error type
|
||||
args: {
|
||||
workerType: 'transcodegpu',
|
||||
ffmpegPath: 'ffmpeg',
|
||||
jobLog: (t:string) => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(t);
|
||||
},
|
||||
const baseInput = {
|
||||
targetCodec: 'h264',
|
||||
hardwareEncoding: true,
|
||||
hardwareType: 'auto',
|
||||
args: {
|
||||
workerType: 'transcodegpu',
|
||||
ffmpegPath: 'ffmpeg',
|
||||
jobLog: () => {
|
||||
//
|
||||
},
|
||||
});
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
console.log({
|
||||
encoderProperties,
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
void run();
|
||||
interface IcheckHardware {
|
||||
targetCodec:string | undefined,
|
||||
hardwareEncoding:boolean | undefined,
|
||||
hardwareType:string | undefined,
|
||||
ffmpegPath:string | undefined,
|
||||
}
|
||||
|
||||
const checkHardware = async (settings:IcheckHardware):Promise<IgetEncoder> => {
|
||||
const input = JSON.parse(JSON.stringify(baseInput));
|
||||
|
||||
input.args.jobLog = () => {
|
||||
// eslint-disable-next-line no-console
|
||||
// console.log(t);
|
||||
};
|
||||
|
||||
if (settings.targetCodec) {
|
||||
input.targetCodec = settings.targetCodec;
|
||||
}
|
||||
|
||||
if (settings.hardwareEncoding) {
|
||||
input.hardwareEncoding = settings.hardwareEncoding;
|
||||
}
|
||||
|
||||
if (settings.hardwareType) {
|
||||
input.hardwareType = settings.hardwareType;
|
||||
}
|
||||
|
||||
if (settings.ffmpegPath) {
|
||||
input.args.ffmpegPath = settings.ffmpegPath;
|
||||
}
|
||||
|
||||
const encoderProperties = await getEncoder(input);
|
||||
|
||||
return encoderProperties;
|
||||
};
|
||||
|
||||
export default checkHardware;
|
||||
|
|
|
|||
|
|
@ -203,6 +203,16 @@ export const getEncoder = async ({
|
|||
outputArgs: [],
|
||||
filter: '',
|
||||
},
|
||||
{
|
||||
encoder: 'hevc_rkmpp',
|
||||
enabled: false,
|
||||
inputArgs: [
|
||||
'-hwaccel',
|
||||
'rkmpp',
|
||||
],
|
||||
outputArgs: [],
|
||||
filter: '',
|
||||
},
|
||||
{
|
||||
encoder: 'hevc_amf',
|
||||
enabled: false,
|
||||
|
|
@ -275,6 +285,16 @@ export const getEncoder = async ({
|
|||
outputArgs: [],
|
||||
filter: '',
|
||||
},
|
||||
{
|
||||
encoder: 'h264_rkmpp',
|
||||
enabled: false,
|
||||
inputArgs: [
|
||||
'-hwaccel',
|
||||
'rkmpp',
|
||||
],
|
||||
outputArgs: [],
|
||||
filter: '',
|
||||
},
|
||||
{
|
||||
encoder: 'h264_videotoolbox',
|
||||
enabled: false,
|
||||
|
|
|
|||
|
|
@ -111,7 +111,8 @@ export interface Ivariables {
|
|||
user: Record<string, string>,
|
||||
healthCheck?: 'Success',
|
||||
queueTags?: string,
|
||||
liveSizeCompare?: IliveSizeCompare
|
||||
liveSizeCompare?: IliveSizeCompare,
|
||||
removeFromTdarr?: boolean,
|
||||
}
|
||||
|
||||
export interface IpluginOutputArgs {
|
||||
|
|
@ -127,6 +128,10 @@ export interface IpluginInputArgs {
|
|||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
librarySettings: any,
|
||||
inputs: Record<string, unknown>,
|
||||
userVariables: {
|
||||
global: Record<string, string>,
|
||||
library: Record<string, string>,
|
||||
},
|
||||
jobLog: Ilog,
|
||||
workDir: string,
|
||||
platform: string,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue