Skip to content

Commit 37dc4a2

Browse files
committed
Add rdub rename audio classic plugin
1 parent 7b3f9ee commit 37dc4a2

File tree

2 files changed

+241
-0
lines changed

2 files changed

+241
-0
lines changed
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
/* eslint-disable no-console */
2+
const details = () => ({
3+
id: 'Tdarr_Plugin_rdub_audio_rename_channels',
4+
Stage: 'Pre-processing',
5+
Name: 'Rdub Rename Audio Titles',
6+
Type: 'Video',
7+
Operation: 'Transcode',
8+
Description: 'This plugin renames titles for audio streams. '
9+
+ 'An example would be in VLC -> Audio -> Audio Track -> "5.1 - [English]" \n\n'
10+
+ '- 8 Channels will replace the title with 7.1\n '
11+
+ '- 6 Channels will replace the title with 5.1"\n '
12+
+ '- 2 Channels will replace the title with 2.0',
13+
Version: '1.0',
14+
Tags: 'pre-processing,ffmpeg',
15+
Inputs: [],
16+
});
17+
18+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
19+
const plugin = (file, librarySettings, inputs, otherArguments) => {
20+
const lib = require('../methods/lib')();
21+
22+
// eslint-disable-next-line @typescript-eslint/no-unused-vars,no-param-reassign
23+
inputs = lib.loadDefaultValues(inputs, details);
24+
25+
const response = {
26+
processFile: false,
27+
preset: '',
28+
container: `.${file.container}`,
29+
handBrakeMode: false,
30+
FFmpegMode: true,
31+
reQueueAfter: false,
32+
infoLog: '',
33+
};
34+
35+
// Initialize ffmpeg command insert
36+
let ffmpegCommandInsert = '';
37+
let modifyFile = false;
38+
39+
// Check if file is a video. If it isn't, exit the plugin.
40+
if (file.fileMedium !== 'video') {
41+
response.infoLog += '☒ File is not a video. Skipping processing.\n';
42+
response.processFile = false;
43+
return response;
44+
}
45+
46+
// Initialize audioIndex to track audio streams separately
47+
let audioIndex = 0;
48+
49+
// Go through each stream in the file
50+
for (let i = 0; i < file.ffProbeData.streams.length; i += 1) {
51+
// Check if the stream is an audio stream
52+
if (file.ffProbeData.streams[i].codec_type.toLowerCase() === 'audio') {
53+
try {
54+
// Retrieve current title metadata
55+
let currentTitle = file.ffProbeData.streams[i].tags?.title || '';
56+
57+
// Trim whitespace
58+
currentTitle = currentTitle.trim();
59+
60+
// Check if the title matches a standard format ("7.1", "5.1", "2.0")
61+
if (['7.1', '5.1', '2.0'].includes(currentTitle)) {
62+
response.infoLog += `☑ Audio stream ${audioIndex} already has a renamed title: "${currentTitle}".`
63+
+ ' Skipping further renaming.\n';
64+
65+
// Increment audioIndex since we are processing an audio stream
66+
// eslint-disable-next-line no-plusplus
67+
audioIndex++;
68+
69+
// Skip further renaming for this stream
70+
// eslint-disable-next-line no-continue
71+
continue;
72+
}
73+
74+
// Determine new title based on the channel count
75+
let newTitle = '';
76+
if (file.ffProbeData.streams[i].channels === 8) {
77+
newTitle = '7.1';
78+
} else if (file.ffProbeData.streams[i].channels === 6) {
79+
newTitle = '5.1';
80+
} else if (file.ffProbeData.streams[i].channels === 2) {
81+
newTitle = '2.0';
82+
}
83+
84+
// Rename the title if applicable
85+
if (newTitle) {
86+
response.infoLog += `☑ Audio stream ${audioIndex} has ${file.ffProbeData.streams[i].channels} channels. `
87+
+ `Renaming title to "${newTitle}"\n`;
88+
89+
ffmpegCommandInsert += ` -metadata:s:a:${audioIndex} title=${newTitle} `;
90+
modifyFile = true;
91+
}
92+
} catch (err) {
93+
// Log error during audio stream processing
94+
response.infoLog += `Error processing audio stream ${audioIndex}: ${err}\n`;
95+
}
96+
97+
// Increment audioIndex for the next audio stream
98+
// eslint-disable-next-line no-plusplus
99+
audioIndex++;
100+
}
101+
}
102+
103+
// Finalize the command if modifications were made
104+
if (modifyFile) {
105+
response.infoLog += '☒ File has audio tracks to rename. Renaming...\n';
106+
107+
// Set the new preset
108+
response.preset = `, ${ffmpegCommandInsert} -c copy -map 0 -max_muxing_queue_size 9999`;
109+
110+
// Re-queue the file for further processing
111+
response.reQueueAfter = true;
112+
response.processFile = true;
113+
} else {
114+
// No modifications needed
115+
response.infoLog += '☑ File has no need to rename audio streams.\n';
116+
}
117+
118+
return response;
119+
};
120+
121+
module.exports.details = details;
122+
module.exports.plugin = plugin;
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
/* eslint max-len: 0 */
2+
const _ = require('lodash');
3+
const run = require('../helpers/run');
4+
5+
// Test suite for the Tdarr_Plugin_rdub_audio_rename_channels plugin
6+
const pluginTests = [
7+
8+
{
9+
input: {
10+
file: (() => {
11+
const file = _.cloneDeep(require('../sampleData/media/sampleH265_1.json'));
12+
// Simulate a video file with multiple audio streams
13+
file.fileMedium = 'video';
14+
file.ffProbeData.streams = [
15+
{
16+
codec_type: 'audio',
17+
channels: 8,
18+
tags: { title: '' },
19+
},
20+
{
21+
codec_type: 'audio',
22+
channels: 6,
23+
tags: { title: '' },
24+
},
25+
{
26+
codec_type: 'audio',
27+
channels: 2,
28+
tags: { title: '' },
29+
},
30+
];
31+
return file;
32+
})(),
33+
librarySettings: {},
34+
inputs: {},
35+
otherArguments: {},
36+
},
37+
output: {
38+
processFile: true,
39+
preset: ', -metadata:s:a:0 title=7.1 -metadata:s:a:1 title=5.1 -metadata:s:a:2 title=2.0 -c copy -map 0 -max_muxing_queue_size 9999',
40+
container: '.mkv',
41+
handBrakeMode: false,
42+
FFmpegMode: true,
43+
reQueueAfter: true,
44+
infoLog: '☑ Audio stream 0 has 8 channels. Renaming title to "7.1"\n'
45+
+ '☑ Audio stream 1 has 6 channels. Renaming title to "5.1"\n'
46+
+ '☑ Audio stream 2 has 2 channels. Renaming title to "2.0"\n'
47+
+ '☒ File has audio tracks to rename. Renaming...\n',
48+
},
49+
},
50+
51+
{
52+
input: {
53+
file: (() => {
54+
const file = _.cloneDeep(require('../sampleData/media/sampleH265_1.json'));
55+
// Simulate a video file with already renamed audio streams
56+
file.fileMedium = 'video';
57+
file.ffProbeData.streams = [
58+
{
59+
codec_type: 'audio',
60+
channels: 8,
61+
tags: { title: '7.1' },
62+
},
63+
{
64+
codec_type: 'audio',
65+
channels: 6,
66+
tags: { title: '5.1' },
67+
},
68+
{
69+
codec_type: 'audio',
70+
channels: 2,
71+
tags: { title: '2.0' },
72+
},
73+
];
74+
return file;
75+
})(),
76+
librarySettings: {},
77+
inputs: {},
78+
otherArguments: {},
79+
},
80+
output: {
81+
processFile: false,
82+
preset: '',
83+
container: '.mkv',
84+
handBrakeMode: false,
85+
FFmpegMode: true,
86+
reQueueAfter: false,
87+
infoLog: '☑ Audio stream 0 already has a renamed title: "7.1". Skipping further renaming.\n'
88+
+ '☑ Audio stream 1 already has a renamed title: "5.1". Skipping further renaming.\n'
89+
+ '☑ Audio stream 2 already has a renamed title: "2.0". Skipping further renaming.\n'
90+
+ '☑ File has no need to rename audio streams.\n',
91+
},
92+
},
93+
94+
{
95+
input: {
96+
file: (() => {
97+
const file = _.cloneDeep(require('../sampleData/media/sampleH265_1.json'));
98+
// Simulate a non-video file
99+
file.fileMedium = 'audio';
100+
file.ffProbeData.streams = [];
101+
return file;
102+
})(),
103+
librarySettings: {},
104+
inputs: {},
105+
otherArguments: {},
106+
},
107+
output: {
108+
processFile: false,
109+
preset: '',
110+
container: '.mkv',
111+
handBrakeMode: false,
112+
FFmpegMode: true,
113+
reQueueAfter: false,
114+
infoLog: '☒ File is not a video. Skipping processing.\n',
115+
},
116+
},
117+
];
118+
119+
void run(pluginTests);

0 commit comments

Comments
 (0)