sfxmix 1.0.8 → 1.1.2
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/README.md +26 -43
- package/demo/demo_6.mjs +14 -0
- package/demo/demo_7.mjs +14 -0
- package/index.js +42 -31
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
- **Concatenate** multiple audio files seamlessly.
|
|
10
10
|
- **Mix** audio tracks with adjustable durations.
|
|
11
11
|
- **Insert silence** at any point in your audio sequence.
|
|
12
|
-
- **Apply filters** like echo,
|
|
12
|
+
- **Apply filters** like echo, normalize, highpass, lowpass, volume, equalizer, flanger, pitch, tremolo, phaser, tempo, and more.
|
|
13
13
|
- **Parameterizable filters** for fine-grained control.
|
|
14
14
|
- **Fluent interface** for chaining multiple operations.
|
|
15
15
|
|
|
@@ -116,6 +116,15 @@ sfx
|
|
|
116
116
|
.save('enhanced_announcement.mp3');
|
|
117
117
|
```
|
|
118
118
|
|
|
119
|
+
### 6. Change Tempo of Audio
|
|
120
|
+
|
|
121
|
+
```javascript
|
|
122
|
+
sfx
|
|
123
|
+
.add('speech.mp3')
|
|
124
|
+
.filter('tempo', { x: 1.25 }) // Increase tempo by 25%
|
|
125
|
+
.save('faster_speech.mp3');
|
|
126
|
+
```
|
|
127
|
+
|
|
119
128
|
---
|
|
120
129
|
|
|
121
130
|
## 📖 API Documentation
|
|
@@ -196,16 +205,15 @@ Applies an audio filter to the current audio.
|
|
|
196
205
|
- [`normalize`](#filter-normalize)
|
|
197
206
|
- [`telephone`](#filter-telephone)
|
|
198
207
|
- [`echo`](#filter-echo)
|
|
199
|
-
- [`reverb`](#filter-reverb)
|
|
200
208
|
- [`highpass`](#filter-highpass)
|
|
201
209
|
- [`lowpass`](#filter-lowpass)
|
|
202
210
|
- [`volume`](#filter-volume)
|
|
203
211
|
- [`equalizer`](#filter-equalizer)
|
|
204
|
-
- [`compressor`](#filter-compressor)
|
|
205
212
|
- [`flanger`](#filter-flanger)
|
|
206
213
|
- [`pitch`](#filter-pitch)
|
|
207
214
|
- [`tremolo`](#filter-tremolo)
|
|
208
215
|
- [`phaser`](#filter-phaser)
|
|
216
|
+
- [`tempo`](#filter-tempo)
|
|
209
217
|
|
|
210
218
|
---
|
|
211
219
|
|
|
@@ -276,28 +284,6 @@ sfx.filter('echo', { delay: 1000, decay: 0.6 });
|
|
|
276
284
|
|
|
277
285
|
---
|
|
278
286
|
|
|
279
|
-
### Filter: `reverb`
|
|
280
|
-
|
|
281
|
-
Applies a reverb effect to the audio.
|
|
282
|
-
|
|
283
|
-
- **Options:**
|
|
284
|
-
- `room_size` (number): Size of the room (default: `50`).
|
|
285
|
-
- `reverberance` (number): Amount of reverberation (default: `50`).
|
|
286
|
-
- `damping` (number): Damping factor (default: `50`).
|
|
287
|
-
- `hf_damping` (number): High-frequency damping (default: `50`).
|
|
288
|
-
- `stereo_depth` (number): Stereo depth (default: `0`).
|
|
289
|
-
- `pre_delay` (number): Pre-delay time in milliseconds (default: `0`).
|
|
290
|
-
- `wet_gain` (number): Gain of the wet signal (default: `0`).
|
|
291
|
-
- `wet_only` (number): If set to `1`, only the wet signal is output (default: `0`).
|
|
292
|
-
|
|
293
|
-
**Example:**
|
|
294
|
-
|
|
295
|
-
```javascript
|
|
296
|
-
sfx.filter('reverb');
|
|
297
|
-
```
|
|
298
|
-
|
|
299
|
-
---
|
|
300
|
-
|
|
301
287
|
### Filter: `highpass`
|
|
302
288
|
|
|
303
289
|
Applies a high-pass filter to remove frequencies below the cutoff.
|
|
@@ -360,24 +346,6 @@ sfx.filter('equalizer', { frequency: 1000, width: 200, gain: -10 });
|
|
|
360
346
|
|
|
361
347
|
---
|
|
362
348
|
|
|
363
|
-
### Filter: `compressor`
|
|
364
|
-
|
|
365
|
-
Applies a dynamic range compressor to the audio.
|
|
366
|
-
|
|
367
|
-
- **Options:**
|
|
368
|
-
- `threshold` (number): Threshold level in dB (default: `-18`).
|
|
369
|
-
- `ratio` (number): Compression ratio (default: `2`).
|
|
370
|
-
- `attack` (number): Attack time in milliseconds (default: `20`).
|
|
371
|
-
- `release` (number): Release time in milliseconds (default: `250`).
|
|
372
|
-
|
|
373
|
-
**Example:**
|
|
374
|
-
|
|
375
|
-
```javascript
|
|
376
|
-
sfx.filter('compressor', { threshold: -20, ratio: 4, attack: 15, release: 300 });
|
|
377
|
-
```
|
|
378
|
-
|
|
379
|
-
---
|
|
380
|
-
|
|
381
349
|
### Filter: `flanger`
|
|
382
350
|
|
|
383
351
|
Applies a flanger effect to the audio.
|
|
@@ -451,6 +419,21 @@ sfx.filter('phaser', { delay: 4, decay: 0.5, speed: 0.8 });
|
|
|
451
419
|
|
|
452
420
|
---
|
|
453
421
|
|
|
422
|
+
### Filter: `tempo`
|
|
423
|
+
|
|
424
|
+
Changes the tempo of the audio without altering its pitch.
|
|
425
|
+
|
|
426
|
+
- **Options:**
|
|
427
|
+
- `x` (number): Tempo change factor (e.g., `1.25` to increase tempo by 25%, `0.8` to decrease by 20%). Must be between `0.5` and `2.0`.
|
|
428
|
+
|
|
429
|
+
**Example:**
|
|
430
|
+
|
|
431
|
+
```javascript
|
|
432
|
+
sfx.filter('tempo', { x: 1.25 }); // Increase tempo by 25%
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
---
|
|
436
|
+
|
|
454
437
|
## ⚠️ Important Notes
|
|
455
438
|
|
|
456
439
|
- **FFmpeg Installation:** Ensure FFmpeg is installed and accessible in your system's PATH.
|
package/demo/demo_6.mjs
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import SfxMix from '../index.js';
|
|
2
|
+
const sfx = new SfxMix();
|
|
3
|
+
|
|
4
|
+
// Slow down part1.mp3 by 25%
|
|
5
|
+
await sfx
|
|
6
|
+
.add('part1.mp3')
|
|
7
|
+
.filter('tempo', { x: 0.75 })
|
|
8
|
+
.save('demo6_part1_slow.mp3')
|
|
9
|
+
.then(() => {
|
|
10
|
+
console.log('Successfully exported: demo6_part1_slow.mp3');
|
|
11
|
+
})
|
|
12
|
+
.catch((error) => {
|
|
13
|
+
console.error('Error during audio processing:', error);
|
|
14
|
+
});
|
package/demo/demo_7.mjs
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import SfxMix from '../index.js';
|
|
2
|
+
const sfx = new SfxMix();
|
|
3
|
+
|
|
4
|
+
// Slow down part1.mp3 by 25%
|
|
5
|
+
await sfx
|
|
6
|
+
.add('part1.mp3')
|
|
7
|
+
.filter('echo', { delays: [1000, 2000, 3000, 4000], decays: [0.5, 0.5, 0.5, 0.5] })
|
|
8
|
+
.save('demo7_part1_echo.mp3')
|
|
9
|
+
.then(() => {
|
|
10
|
+
console.log('Successfully exported: demo7_part1_echo.mp3');
|
|
11
|
+
})
|
|
12
|
+
.catch((error) => {
|
|
13
|
+
console.error('Error during audio processing:', error);
|
|
14
|
+
});
|
package/index.js
CHANGED
|
@@ -95,6 +95,7 @@ class SfxMix {
|
|
|
95
95
|
|
|
96
96
|
resolve(output);
|
|
97
97
|
} catch (err) {
|
|
98
|
+
console.error('Error during audio processing:', err);
|
|
98
99
|
reject(err);
|
|
99
100
|
}
|
|
100
101
|
});
|
|
@@ -221,23 +222,15 @@ function getFilterChain(filterName, options) {
|
|
|
221
222
|
return `highpass=f=${lowFreq}, lowpass=f=${highFreq}`;
|
|
222
223
|
|
|
223
224
|
case 'echo':
|
|
224
|
-
//
|
|
225
|
-
const
|
|
226
|
-
const
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
const reverberance = options.reverberance !== undefined ? options.reverberance : 50;
|
|
234
|
-
const damping = options.damping !== undefined ? options.damping : 50;
|
|
235
|
-
const hf_damping = options.hf_damping !== undefined ? options.hf_damping : 50;
|
|
236
|
-
const stereo_depth = options.stereo_depth !== undefined ? options.stereo_depth : 0;
|
|
237
|
-
const pre_delay = options.pre_delay !== undefined ? options.pre_delay : 0;
|
|
238
|
-
const wet_gain = options.wet_gain !== undefined ? options.wet_gain : 0;
|
|
239
|
-
const wet_only = options.wet_only !== undefined ? options.wet_only : 0;
|
|
240
|
-
return `areverb=room_size=${room_size}:reverberance=${reverberance}:damping=${damping}:hf_damping=${hf_damping}:stereo_depth=${stereo_depth}:pre_delay=${pre_delay}:wet_gain=${wet_gain}:wet_only=${wet_only}`;
|
|
225
|
+
// Reverb effect using aecho filter
|
|
226
|
+
const inGain = options.inGain !== undefined ? options.inGain : 0.8;
|
|
227
|
+
const outGain = options.outGain !== undefined ? options.outGain : 0.9;
|
|
228
|
+
const delays = options.delays !== undefined ? options.delays : [1, 200, 300, 400];
|
|
229
|
+
const decays = options.decays !== undefined ? options.decays : [0.5, 0.5, 0.5, 0.5];
|
|
230
|
+
|
|
231
|
+
const delaysStr = delays.join('|');
|
|
232
|
+
const decaysStr = decays.join('|');
|
|
233
|
+
return `aecho=${inGain}:${outGain}:${delaysStr}:${decaysStr}`;
|
|
241
234
|
|
|
242
235
|
case 'highpass':
|
|
243
236
|
// High-pass filter
|
|
@@ -271,15 +264,6 @@ function getFilterChain(filterName, options) {
|
|
|
271
264
|
throw new Error('Equalizer filter requires "frequency", "width", and "gain" options.');
|
|
272
265
|
}
|
|
273
266
|
|
|
274
|
-
case 'compressor':
|
|
275
|
-
// Compressor effect
|
|
276
|
-
// Options: threshold, ratio, attack, release
|
|
277
|
-
const threshold = options.threshold !== undefined ? options.threshold : -18;
|
|
278
|
-
const ratio = options.ratio !== undefined ? options.ratio : 2;
|
|
279
|
-
const attack = options.attack !== undefined ? options.attack : 20;
|
|
280
|
-
const release = options.release !== undefined ? options.release : 250;
|
|
281
|
-
return `acompressor=threshold=${threshold}:ratio=${ratio}:attack=${attack}:release=${release}`;
|
|
282
|
-
|
|
283
267
|
case 'flanger':
|
|
284
268
|
// Flanger effect
|
|
285
269
|
// Options: delay, depth, regen, width, speed, shape, phase, interp
|
|
@@ -291,7 +275,7 @@ function getFilterChain(filterName, options) {
|
|
|
291
275
|
const shape = options.shape !== undefined ? options.shape : 'sine';
|
|
292
276
|
const phase = options.phase !== undefined ? options.phase : 25;
|
|
293
277
|
const interp = options.interp !== undefined ? options.interp : 'linear';
|
|
294
|
-
return `
|
|
278
|
+
return `aflanger=delay=${flangerDelay}:depth=${depth}:regen=${regen}:width=${width}:speed=${speed}:shape=${shape}:phase=${phase}:interp=${interp}`;
|
|
295
279
|
|
|
296
280
|
case 'pitch':
|
|
297
281
|
// Pitch shift effect
|
|
@@ -305,10 +289,9 @@ function getFilterChain(filterName, options) {
|
|
|
305
289
|
|
|
306
290
|
case 'tremolo':
|
|
307
291
|
// Tremolo effect
|
|
308
|
-
// Options:
|
|
309
|
-
const
|
|
310
|
-
|
|
311
|
-
return `tremolo=f=${tremoloSpeed}:d=${tremoloDepth}`;
|
|
292
|
+
// Options: frequency
|
|
293
|
+
const frequency = options.frequency !== undefined ? options.frequency : 1;
|
|
294
|
+
return `tremolo=f=${frequency}`;
|
|
312
295
|
|
|
313
296
|
case 'phaser':
|
|
314
297
|
// Phaser effect
|
|
@@ -321,6 +304,34 @@ function getFilterChain(filterName, options) {
|
|
|
321
304
|
const type = options.type !== undefined ? options.type : 0;
|
|
322
305
|
return `aphaser=in_gain=${in_gain}:out_gain=${out_gain}:delay=${delay}:decay=${decay}:speed=${speed_ph}:type=${type}`;
|
|
323
306
|
|
|
307
|
+
case 'tempo':
|
|
308
|
+
// Change the speed without changing the tone
|
|
309
|
+
// Options: x (speed factor, between 0.5 and 2.0)
|
|
310
|
+
if (options.x !== undefined) {
|
|
311
|
+
const tempo = options.x;
|
|
312
|
+
if (tempo < 0.5 || tempo > 2.0) {
|
|
313
|
+
// If the value is outside the supported range, chain filters
|
|
314
|
+
const tempos = [];
|
|
315
|
+
let remainingTempo = tempo;
|
|
316
|
+
while (remainingTempo < 0.5 || remainingTempo > 2.0) {
|
|
317
|
+
if (remainingTempo < 0.5) {
|
|
318
|
+
tempos.push(0.5);
|
|
319
|
+
remainingTempo /= 0.5;
|
|
320
|
+
} else {
|
|
321
|
+
tempos.push(2.0);
|
|
322
|
+
remainingTempo /= 2.0;
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
tempos.push(remainingTempo);
|
|
326
|
+
const atempoFilters = tempos.map(t => `atempo=${t}`).join(',');
|
|
327
|
+
return atempoFilters;
|
|
328
|
+
} else {
|
|
329
|
+
return `atempo=${tempo}`;
|
|
330
|
+
}
|
|
331
|
+
} else {
|
|
332
|
+
throw new Error('The tempo filter requires the "x" option.');
|
|
333
|
+
}
|
|
334
|
+
|
|
324
335
|
default:
|
|
325
336
|
throw new Error(`Unknown filter: ${filterName}`);
|
|
326
337
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sfxmix",
|
|
3
|
-
"description": "🎧 SfxMix -
|
|
4
|
-
"version": "1.
|
|
3
|
+
"description": "🎧 SfxMix - Powerful and easy-to-use module for processing audio.",
|
|
4
|
+
"version": "1.1.2",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"dependencies": {
|
|
7
7
|
"fluent-ffmpeg": "^2.1.3",
|