@mediaproc/audio 1.1.0 ā 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +19 -4
- package/dist/cli.js.map +1 -1
- package/dist/commands/convert.d.ts.map +1 -1
- package/dist/commands/convert.js +86 -40
- package/dist/commands/convert.js.map +1 -1
- package/dist/commands/extract.d.ts.map +1 -1
- package/dist/commands/extract.js +111 -43
- package/dist/commands/extract.js.map +1 -1
- package/dist/commands/merge.d.ts.map +1 -1
- package/dist/commands/merge.js +106 -40
- package/dist/commands/merge.js.map +1 -1
- package/dist/commands/normalize.d.ts.map +1 -1
- package/dist/commands/normalize.js +94 -31
- package/dist/commands/normalize.js.map +1 -1
- package/dist/commands/trim.d.ts.map +1 -1
- package/dist/commands/trim.js +47 -23
- package/dist/commands/trim.js.map +1 -1
- package/dist/register.d.ts +2 -1
- package/dist/register.d.ts.map +1 -1
- package/dist/register.js +22 -9
- package/dist/register.js.map +1 -1
- package/dist/types.d.ts +30 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/ffmpeg-output.d.ts +13 -0
- package/dist/utils/ffmpeg-output.d.ts.map +1 -0
- package/dist/utils/ffmpeg-output.js +86 -0
- package/dist/utils/ffmpeg-output.js.map +1 -0
- package/dist/utils/ffmpeg.d.ts +9 -8
- package/dist/utils/ffmpeg.d.ts.map +1 -1
- package/dist/utils/ffmpeg.js +107 -28
- package/dist/utils/ffmpeg.js.map +1 -1
- package/dist/utils/ffmpegLogger.d.ts +12 -0
- package/dist/utils/ffmpegLogger.d.ts.map +1 -0
- package/dist/utils/ffmpegLogger.js +34 -0
- package/dist/utils/ffmpegLogger.js.map +1 -0
- package/package.json +4 -8
- package/bin/cli.js +0 -5
package/dist/commands/merge.js
CHANGED
|
@@ -1,21 +1,27 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
2
|
import { stat, writeFile, unlink } from 'fs/promises';
|
|
3
3
|
import { join, dirname } from 'path';
|
|
4
|
-
import { runFFmpeg, getAudioMetadata, checkFFmpeg, formatFileSize, formatDuration
|
|
5
|
-
import {
|
|
4
|
+
import { runFFmpeg, getAudioMetadata, checkFFmpeg, formatFileSize, formatDuration } from '../utils/ffmpeg.js';
|
|
5
|
+
import { styleFFmpegOutput, shouldDisplayLine } from '../utils/ffmpeg-output.js';
|
|
6
|
+
import { AUDIO_EXTENSIONS, validatePaths, createStandardHelp, resolveOutputPaths } from '@mediaproc/core';
|
|
6
7
|
import ora from 'ora';
|
|
7
8
|
export function mergeCommand(audioCmd) {
|
|
8
9
|
audioCmd
|
|
9
10
|
.command('merge [inputs...]')
|
|
10
11
|
.description('Merge multiple audio files into one')
|
|
11
|
-
.option('-o, --output <path>', 'Output file path
|
|
12
|
+
.option('-o, --output <path>', 'Output file path (must include extension)')
|
|
12
13
|
.option('--format <format>', 'Output format: mp3, aac, wav, flac, ogg', 'mp3')
|
|
14
|
+
.option('--codec <codec>', 'Specify output audio codec (overrides default for format)')
|
|
13
15
|
.option('--bitrate <bitrate>', 'Output bitrate (e.g., 192k, 320k)', '192k')
|
|
14
16
|
.option('--crossfade <seconds>', 'Crossfade duration between files (seconds)', parseFloat)
|
|
15
17
|
.option('--normalize', 'Normalize audio levels before merging')
|
|
18
|
+
.option('--fade-in <seconds>', 'Add fade-in effect (seconds)', parseFloat)
|
|
19
|
+
.option('--fade-out <seconds>', 'Add fade-out effect (seconds)', parseFloat)
|
|
20
|
+
.option('--remove-silence', 'Remove silence between tracks')
|
|
21
|
+
.option('--metadata <key=value>', 'Set custom metadata (repeatable)', (val, acc = []) => { acc.push(val); return acc; }, [])
|
|
16
22
|
.option('--dry-run', 'Preview command without executing')
|
|
17
23
|
.option('-v, --verbose', 'Show detailed FFmpeg output')
|
|
18
|
-
.option('--explain', '
|
|
24
|
+
.option('--explain [mode]', 'Show a detailed explanation of what this command will do, including technical and human-readable output. Modes: human, details, json. Adds context like timestamp, user, and platform.')
|
|
19
25
|
.option('-h, --help', 'Display help for merge command')
|
|
20
26
|
.action(async (inputs, options) => {
|
|
21
27
|
if (options.help || !inputs || inputs.length === 0) {
|
|
@@ -35,7 +41,7 @@ export function mergeCommand(audioCmd) {
|
|
|
35
41
|
{ flag: '--crossfade <seconds>', description: 'Crossfade duration between files in seconds (0-10)' },
|
|
36
42
|
{ flag: '--normalize', description: 'Normalize audio levels before merging for consistent volume' },
|
|
37
43
|
{ flag: '--dry-run', description: 'Preview FFmpeg command without executing' },
|
|
38
|
-
{ flag: '--explain', description: '
|
|
44
|
+
{ flag: '--explain [mode]', description: 'Show a detailed explanation of what this command will do, including technical and human-readable output. Modes: human, details, json. Adds context like timestamp, user, and platform.' },
|
|
39
45
|
{ flag: '-v, --verbose', description: 'Show detailed FFmpeg output and progress' }
|
|
40
46
|
],
|
|
41
47
|
examples: [
|
|
@@ -58,40 +64,61 @@ export function mergeCommand(audioCmd) {
|
|
|
58
64
|
console.error(chalk.red('\nā Error: At least 2 audio files required for merging'));
|
|
59
65
|
process.exit(1);
|
|
60
66
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
try {
|
|
66
|
-
const paths = parseInputPaths(input, AUDIO_EXTENSIONS);
|
|
67
|
-
validatedInputs.push(...paths);
|
|
68
|
-
}
|
|
69
|
-
catch (err) {
|
|
70
|
-
console.warn(chalk.yellow(`ā Skipping invalid input: ${input}`));
|
|
71
|
-
}
|
|
67
|
+
// Provide default output file name if not provided
|
|
68
|
+
let outputPathArg = options.output;
|
|
69
|
+
if (!outputPathArg) {
|
|
70
|
+
outputPathArg = 'merged.mp3';
|
|
72
71
|
}
|
|
73
|
-
|
|
72
|
+
// Use pathValidator for all input/output validation
|
|
73
|
+
const { inputFiles, outputPath, errors } = validatePaths(inputs.join(','), outputPathArg, { allowedExtensions: AUDIO_EXTENSIONS });
|
|
74
|
+
if (errors.length > 0) {
|
|
75
|
+
errors.forEach(e => console.error(chalk.red(e)));
|
|
76
|
+
process.exit(1);
|
|
77
|
+
}
|
|
78
|
+
if (inputFiles.length < 2) {
|
|
74
79
|
console.error(chalk.red('\nā Error: Not enough valid audio files found'));
|
|
75
80
|
process.exit(1);
|
|
76
81
|
}
|
|
77
|
-
//
|
|
82
|
+
// Always use resolveOutputPaths to generate output file(s)
|
|
83
|
+
const outputFormat = options.format || 'mp3';
|
|
84
|
+
const outputPathsMap = resolveOutputPaths(inputFiles, outputPath, {
|
|
85
|
+
suffix: '-merged',
|
|
86
|
+
newExtension: `.${outputFormat}`
|
|
87
|
+
});
|
|
88
|
+
const outputFiles = Array.from(outputPathsMap.values());
|
|
89
|
+
console.log(chalk.blue(`\nš Merging ${inputFiles.length} audio files...`));
|
|
90
|
+
// Show input files and collect extensions
|
|
78
91
|
let totalDuration = 0;
|
|
79
|
-
for (const inputFile of
|
|
92
|
+
for (const inputFile of inputFiles) {
|
|
80
93
|
const metadata = await getAudioMetadata(inputFile);
|
|
81
94
|
console.log(chalk.dim(` ${inputFile} (${formatDuration(metadata.duration)})`));
|
|
82
95
|
totalDuration += metadata.duration;
|
|
83
96
|
}
|
|
84
97
|
console.log(chalk.dim(`\nTotal duration: ${formatDuration(totalDuration)}`));
|
|
85
98
|
// Create concat file list
|
|
86
|
-
const concatFile = join(dirname(
|
|
87
|
-
const concatContent =
|
|
99
|
+
const concatFile = join(dirname(inputFiles[0]), '.concat-list.txt');
|
|
100
|
+
const concatContent = inputFiles.map(f => `file '${f}'`).join('\n');
|
|
88
101
|
await writeFile(concatFile, concatContent);
|
|
89
102
|
const args = ['-f', 'concat', '-safe', '0', '-i', concatFile, '-y'];
|
|
90
|
-
//
|
|
103
|
+
// Output codec selection
|
|
104
|
+
const codecMap = {
|
|
105
|
+
mp3: 'libmp3lame',
|
|
106
|
+
aac: 'aac',
|
|
107
|
+
flac: 'flac',
|
|
108
|
+
wav: 'pcm_s16le',
|
|
109
|
+
ogg: 'libvorbis',
|
|
110
|
+
};
|
|
111
|
+
let codec = options.codec || codecMap[outputFormat] || 'libmp3lame';
|
|
112
|
+
if (codec)
|
|
113
|
+
args.push('-c:a', codec);
|
|
114
|
+
if (options.bitrate)
|
|
115
|
+
args.push('-b:a', options.bitrate);
|
|
116
|
+
// Audio filter chain
|
|
117
|
+
let filterChain = '';
|
|
118
|
+
// Crossfade
|
|
91
119
|
if (options.crossfade) {
|
|
92
|
-
// Build complex filter for crossfade
|
|
93
120
|
const filterParts = [];
|
|
94
|
-
for (let i = 0; i <
|
|
121
|
+
for (let i = 0; i < inputFiles.length - 1; i++) {
|
|
95
122
|
if (i === 0) {
|
|
96
123
|
filterParts.push(`[0:a][1:a]acrossfade=d=${options.crossfade}[a01]`);
|
|
97
124
|
}
|
|
@@ -100,40 +127,79 @@ export function mergeCommand(audioCmd) {
|
|
|
100
127
|
}
|
|
101
128
|
}
|
|
102
129
|
args.push('-filter_complex', filterParts.join(';'));
|
|
103
|
-
args.push('-map', `[a0${
|
|
130
|
+
args.push('-map', `[a0${inputFiles.length - 1}]`);
|
|
104
131
|
}
|
|
105
|
-
// Normalization
|
|
132
|
+
// Normalization (if not crossfade)
|
|
106
133
|
if (options.normalize && !options.crossfade) {
|
|
107
|
-
|
|
134
|
+
filterChain += (filterChain ? ',' : '') + 'loudnorm=I=-16:TP=-1.5:LRA=11';
|
|
135
|
+
}
|
|
136
|
+
// Fade in/out
|
|
137
|
+
if (options.fadeIn) {
|
|
138
|
+
filterChain += (filterChain ? ',' : '') + `afade=t=in:st=0:d=${options.fadeIn}`;
|
|
139
|
+
}
|
|
140
|
+
if (options.fadeOut && totalDuration) {
|
|
141
|
+
const fadeStart = totalDuration - options.fadeOut;
|
|
142
|
+
filterChain += (filterChain ? ',' : '') + `afade=t=out:st=${fadeStart}:d=${options.fadeOut}`;
|
|
143
|
+
}
|
|
144
|
+
// Silence removal
|
|
145
|
+
if (options.removeSilence) {
|
|
146
|
+
filterChain += (filterChain ? ',' : '') + 'silenceremove=start_periods=1:start_silence=0.1:start_threshold=-50dB';
|
|
147
|
+
}
|
|
148
|
+
if (filterChain && !options.crossfade) {
|
|
149
|
+
args.push('-af', filterChain);
|
|
150
|
+
}
|
|
151
|
+
// Metadata
|
|
152
|
+
if (options.metadata && Array.isArray(options.metadata)) {
|
|
153
|
+
for (const entry of options.metadata) {
|
|
154
|
+
const [key, value] = entry.split('=');
|
|
155
|
+
if (key && value)
|
|
156
|
+
args.push('-metadata', `${key}=${value}`);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
// Output file (merge always produces a single output file)
|
|
160
|
+
if (outputFiles.length > 0) {
|
|
161
|
+
args.push(outputFiles[0]);
|
|
108
162
|
}
|
|
109
|
-
// Output bitrate
|
|
110
|
-
args.push('-b:a', options.bitrate);
|
|
111
|
-
args.push(options.output);
|
|
112
163
|
if (options.dryRun) {
|
|
113
164
|
console.log(chalk.yellow('\n[DRY RUN] Would execute:'));
|
|
114
165
|
console.log(chalk.dim(`ffmpeg ${args.join(' ')}`));
|
|
115
166
|
await unlink(concatFile);
|
|
116
|
-
showPluginBranding('Audio', '../../package.json');
|
|
117
167
|
return;
|
|
118
168
|
}
|
|
119
|
-
if (options.explain) {
|
|
120
|
-
console.log(chalk.gray('Explain mode is not yet available.'));
|
|
121
|
-
console.log(chalk.cyan('Planned for v0.8.x.'));
|
|
122
|
-
}
|
|
123
169
|
const spinner = ora('Merging audio files...').start();
|
|
124
170
|
try {
|
|
125
|
-
await runFFmpeg(args, options.verbose)
|
|
126
|
-
|
|
171
|
+
await runFFmpeg(args, options.verbose, (line) => {
|
|
172
|
+
if (shouldDisplayLine(line, options.verbose ?? false)) {
|
|
173
|
+
console.log(styleFFmpegOutput(line));
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
let outputStat;
|
|
177
|
+
if (outputPath) {
|
|
178
|
+
outputStat = await stat(outputPath);
|
|
179
|
+
}
|
|
127
180
|
// Clean up concat file
|
|
128
181
|
await unlink(concatFile);
|
|
129
182
|
spinner.succeed(chalk.green('Merge complete'));
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
183
|
+
if (outputPath) {
|
|
184
|
+
console.log(chalk.green(`ā Output: ${outputPath}`));
|
|
185
|
+
if (outputStat) {
|
|
186
|
+
console.log(chalk.dim(`Duration: ${formatDuration(totalDuration)} ⢠Size: ${formatFileSize(outputStat.size)}`));
|
|
187
|
+
}
|
|
188
|
+
}
|
|
133
189
|
}
|
|
134
190
|
catch (error) {
|
|
135
191
|
await unlink(concatFile).catch(() => { });
|
|
136
192
|
spinner.fail(chalk.red('Merge failed'));
|
|
193
|
+
// Enhanced error reporting for common ffmpeg concat/decoder issues
|
|
194
|
+
const errObj = error;
|
|
195
|
+
const errMsg = (errObj && errObj.message) ? errObj.message : String(error);
|
|
196
|
+
if (/Invalid data found when processing input|Error submitting packet to decoder/i.test(errMsg)) {
|
|
197
|
+
console.error(chalk.yellow('\nā ļø One or more input files may be corrupted, incompatible, or not suitable for merging.'));
|
|
198
|
+
console.error(chalk.yellow('Please ensure all input files are valid, have the same codec/sample rate/channels, and are not damaged.'));
|
|
199
|
+
}
|
|
200
|
+
else if (/Unable to choose an output format|Invalid argument|Error opening output file/i.test(errMsg)) {
|
|
201
|
+
console.error(chalk.yellow('\nā ļø Output path or format may be invalid. Make sure the output file has a valid extension and is not a directory.'));
|
|
202
|
+
}
|
|
137
203
|
throw error;
|
|
138
204
|
}
|
|
139
205
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"merge.js","sourceRoot":"","sources":["../../src/commands/merge.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACrC,OAAO,
|
|
1
|
+
{"version":3,"file":"merge.js","sourceRoot":"","sources":["../../src/commands/merge.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"normalize.d.ts","sourceRoot":"","sources":["../../src/commands/normalize.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"normalize.d.ts","sourceRoot":"","sources":["../../src/commands/normalize.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AASzC,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI,CA4LxD"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
2
|
import { stat } from 'fs/promises';
|
|
3
|
-
import { runFFmpeg, getAudioMetadata, checkFFmpeg, formatFileSize, formatDuration
|
|
4
|
-
import {
|
|
3
|
+
import { runFFmpeg, getAudioMetadata, checkFFmpeg, formatFileSize, formatDuration } from '../utils/ffmpeg.js';
|
|
4
|
+
import { styleFFmpegOutput, shouldDisplayLine } from '../utils/ffmpeg-output.js';
|
|
5
|
+
import { AUDIO_EXTENSIONS, validatePaths, resolveOutputPaths, createStandardHelp } from '@mediaproc/core';
|
|
5
6
|
import ora from 'ora';
|
|
6
7
|
export function normalizeCommand(audioCmd) {
|
|
7
8
|
audioCmd
|
|
@@ -14,9 +15,9 @@ export function normalizeCommand(audioCmd) {
|
|
|
14
15
|
.option('--format <format>', 'Output format (default: same as input)')
|
|
15
16
|
.option('--dry-run', 'Preview command without executing')
|
|
16
17
|
.option('-v, --verbose', 'Show detailed FFmpeg output')
|
|
17
|
-
.option('--explain', '
|
|
18
|
+
.option('--explain [mode]', 'Show a detailed explanation of what this command will do, including technical and human-readable output. Modes: human, details, json. Adds context like timestamp, user, and platform.')
|
|
18
19
|
.option('-h, --help', 'Display help for normalize command')
|
|
19
|
-
.action(async (input, options)
|
|
20
|
+
.action(async function (input, options) {
|
|
20
21
|
if (options.help || !input) {
|
|
21
22
|
createStandardHelp({
|
|
22
23
|
commandName: 'normalize',
|
|
@@ -34,7 +35,7 @@ export function normalizeCommand(audioCmd) {
|
|
|
34
35
|
{ flag: '-m, --method <method>', description: 'Normalization method: loudnorm (EBU R128 standard), peak' },
|
|
35
36
|
{ flag: '--format <format>', description: 'Output format: mp3, aac, wav, flac (default: same as input)' },
|
|
36
37
|
{ flag: '--dry-run', description: 'Preview FFmpeg command without executing' },
|
|
37
|
-
{ flag: '--explain', description: '
|
|
38
|
+
{ flag: '--explain [mode]', description: 'Show a detailed explanation of what this command will do, including technical and human-readable output. Modes: human, details, json. Adds context like timestamp, user, and platform.' },
|
|
38
39
|
{ flag: '-v, --verbose', description: 'Show detailed FFmpeg output and progress' }
|
|
39
40
|
],
|
|
40
41
|
examples: [
|
|
@@ -53,14 +54,31 @@ export function normalizeCommand(audioCmd) {
|
|
|
53
54
|
console.error(chalk.red('\nā FFmpeg not found. Please install FFmpeg first.'));
|
|
54
55
|
process.exit(1);
|
|
55
56
|
}
|
|
56
|
-
const
|
|
57
|
+
const { inputFiles, outputPath, errors } = validatePaths(input, options.output, { allowedExtensions: AUDIO_EXTENSIONS });
|
|
58
|
+
if (errors.length > 0) {
|
|
59
|
+
errors.forEach(e => console.error(chalk.red(e)));
|
|
60
|
+
process.exit(1);
|
|
61
|
+
}
|
|
57
62
|
const suffix = options.format ? `-normalized.${options.format}` : '-normalized';
|
|
58
|
-
const
|
|
59
|
-
const outputPathsMap = resolveOutputPaths(inputPaths, outputPath, { suffix });
|
|
63
|
+
const outputPathsMap = resolveOutputPaths(inputFiles, outputPath, { suffix });
|
|
60
64
|
const outputPaths = Array.from(outputPathsMap.values());
|
|
61
|
-
for (let i = 0; i <
|
|
62
|
-
const inputFile =
|
|
65
|
+
for (let i = 0; i < inputFiles.length; i++) {
|
|
66
|
+
const inputFile = inputFiles[i];
|
|
63
67
|
const outputFile = outputPaths[i];
|
|
68
|
+
// Warn if normalization is requested for a format known to be problematic
|
|
69
|
+
const unsupportedNormFormats = ['ogg'];
|
|
70
|
+
let outFormat = options.format;
|
|
71
|
+
if (!outFormat) {
|
|
72
|
+
const extMatch = outputFile.match(/\.([a-zA-Z0-9]+)$/);
|
|
73
|
+
outFormat = extMatch && [
|
|
74
|
+
'mp3', 'wav', 'flac', 'aac', 'ogg', 'm4a', 'wma', 'opus', 'ape', 'alac', 'mov', 'mkv'
|
|
75
|
+
].includes(extMatch[1].toLowerCase())
|
|
76
|
+
? extMatch[1].toLowerCase()
|
|
77
|
+
: undefined;
|
|
78
|
+
}
|
|
79
|
+
if (outFormat && unsupportedNormFormats.includes(outFormat) && (options.method === 'loudnorm' || options.method === 'peak')) {
|
|
80
|
+
console.warn(chalk.yellow(`ā ļø Warning: Normalization for format '${outFormat}' may not be supported or may fail. If you encounter errors, try using a different output format (e.g., wav, flac, mp3, aac).`));
|
|
81
|
+
}
|
|
64
82
|
console.log(chalk.blue(`\nš Normalizing: ${inputFile}`));
|
|
65
83
|
const metadata = await getAudioMetadata(inputFile);
|
|
66
84
|
const inputStat = await stat(inputFile);
|
|
@@ -68,16 +86,50 @@ export function normalizeCommand(audioCmd) {
|
|
|
68
86
|
`Sample Rate: ${metadata.sampleRate} Hz ⢠` +
|
|
69
87
|
`Channels: ${metadata.channels}`));
|
|
70
88
|
const args = ['-i', inputFile, '-y'];
|
|
89
|
+
let filterApplied = false;
|
|
71
90
|
if (options.method === 'loudnorm') {
|
|
72
|
-
// EBU R128 loudness normalization
|
|
73
91
|
args.push('-af', `loudnorm=I=${options.target}:TP=${options.maxLevel}:LRA=11:print_format=summary`);
|
|
92
|
+
filterApplied = true;
|
|
74
93
|
}
|
|
75
94
|
else if (options.method === 'peak') {
|
|
76
|
-
// Simple peak normalization
|
|
77
95
|
args.push('-af', 'volume=0dB');
|
|
96
|
+
filterApplied = true;
|
|
78
97
|
}
|
|
79
|
-
//
|
|
80
|
-
if (!
|
|
98
|
+
// Determine output format and codec
|
|
99
|
+
if (!outFormat) {
|
|
100
|
+
const extMatch = outputFile.match(/\.([a-zA-Z0-9]+)$/);
|
|
101
|
+
outFormat = extMatch && [
|
|
102
|
+
'mp3', 'wav', 'flac', 'aac', 'ogg', 'm4a', 'wma', 'opus', 'ape', 'alac', 'mov', 'mkv'
|
|
103
|
+
].includes(extMatch[1].toLowerCase())
|
|
104
|
+
? extMatch[1].toLowerCase()
|
|
105
|
+
: undefined;
|
|
106
|
+
}
|
|
107
|
+
// Prevent filter+streamcopy: show error if user tries to use filters with stream copy
|
|
108
|
+
if (filterApplied) {
|
|
109
|
+
if (outFormat === 'mp3') {
|
|
110
|
+
args.push('-c:a', 'libmp3lame');
|
|
111
|
+
}
|
|
112
|
+
else if (outFormat === 'aac' || outFormat === 'm4a') {
|
|
113
|
+
args.push('-c:a', 'aac');
|
|
114
|
+
}
|
|
115
|
+
else if (outFormat === 'flac') {
|
|
116
|
+
args.push('-c:a', 'flac');
|
|
117
|
+
}
|
|
118
|
+
else if (outFormat === 'wav') {
|
|
119
|
+
args.push('-c:a', 'pcm_s16le');
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
args.push('-c:a', 'libmp3lame'); // Default to mp3 codec for safety
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
// No filter: safe to streamcopy
|
|
127
|
+
// But if user tries to add a filter (e.g. via method=peak) and also requests stream copy, show error
|
|
128
|
+
if (options.method === 'peak' || options.method === 'loudnorm') {
|
|
129
|
+
// Defensive: should not happen, but catch any logic error
|
|
130
|
+
console.error(chalk.red('\nā Error: Cannot use normalization filters with stream copy. Please remove normalization options or use a supported codec.'));
|
|
131
|
+
process.exit(1);
|
|
132
|
+
}
|
|
81
133
|
args.push('-c:a', 'copy');
|
|
82
134
|
}
|
|
83
135
|
args.push(outputFile);
|
|
@@ -86,28 +138,39 @@ export function normalizeCommand(audioCmd) {
|
|
|
86
138
|
console.log(chalk.dim(`ffmpeg ${args.join(' ')}`));
|
|
87
139
|
continue;
|
|
88
140
|
}
|
|
89
|
-
if (options.explain) {
|
|
90
|
-
console.log(chalk.gray('Explain mode is not yet available.'));
|
|
91
|
-
console.log(chalk.cyan('Planned for v0.8.x.'));
|
|
92
|
-
}
|
|
93
141
|
const spinner = ora('Normalizing...').start();
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
142
|
+
// Capture FFmpeg output to parse measured LUFS
|
|
143
|
+
let measuredLufs = undefined;
|
|
144
|
+
await runFFmpeg(args, options.verbose ?? false, (line) => {
|
|
145
|
+
if (shouldDisplayLine(line, options.verbose ?? false)) {
|
|
146
|
+
console.log(styleFFmpegOutput(line));
|
|
147
|
+
}
|
|
148
|
+
// Parse measured_I from loudnorm summary
|
|
149
|
+
if (options.method === 'loudnorm') {
|
|
150
|
+
const match = line.match(/Measured_I:\s*(-?\d+\.?\d*)/);
|
|
151
|
+
if (match)
|
|
152
|
+
measuredLufs = match[1];
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
const outputStat = await stat(outputFile);
|
|
156
|
+
spinner.succeed(chalk.green('Normalization complete'));
|
|
157
|
+
console.log(chalk.green(`ā Output: ${outputFile}`));
|
|
158
|
+
if (options.method === 'loudnorm') {
|
|
159
|
+
if (measuredLufs !== undefined) {
|
|
160
|
+
console.log(chalk.dim(`Measured: ${measuredLufs} LUFS ⢠Target: ${options.target} LUFS ⢠Peak limit: ${options.maxLevel} dB`));
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
163
|
+
console.log(chalk.dim(`Target: ${options.target} LUFS ⢠Peak limit: ${options.maxLevel} dB (LUFS not available)`));
|
|
164
|
+
}
|
|
101
165
|
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
throw error;
|
|
166
|
+
else {
|
|
167
|
+
console.log(chalk.dim(`Peak limit: ${options.maxLevel} dB`));
|
|
105
168
|
}
|
|
169
|
+
console.log(chalk.dim(`Size: ${formatFileSize(inputStat.size)} ā ${formatFileSize(outputStat.size)}`));
|
|
106
170
|
}
|
|
107
|
-
if (
|
|
108
|
-
console.log(chalk.green(`\nā Normalized ${
|
|
171
|
+
if (inputFiles.length > 1) {
|
|
172
|
+
console.log(chalk.green(`\nā Normalized ${inputFiles.length} files successfully`));
|
|
109
173
|
}
|
|
110
|
-
showPluginBranding('Audio', '../../package.json');
|
|
111
174
|
}
|
|
112
175
|
catch (error) {
|
|
113
176
|
console.error(chalk.red(`\nā Error: ${error.message}`));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"normalize.js","sourceRoot":"","sources":["../../src/commands/normalize.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AACnC,OAAO,
|
|
1
|
+
{"version":3,"file":"normalize.js","sourceRoot":"","sources":["../../src/commands/normalize.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"trim.d.ts","sourceRoot":"","sources":["../../src/commands/trim.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"trim.d.ts","sourceRoot":"","sources":["../../src/commands/trim.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AASzC,wBAAgB,WAAW,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI,CAsLnD"}
|