sfxmix 1.3.0 → 1.3.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/demo/demo_8.js ADDED
@@ -0,0 +1,33 @@
1
+ import SfxMix from '../index.js';
2
+
3
+ // Example 1: Trim silence without padding
4
+ console.log('Example 1: Trimming without padding...');
5
+ const sfx1 = new SfxMix();
6
+ await sfx1
7
+ .add('part1.mp3')
8
+ .trim()
9
+ .save('part1_trimmed.mp3')
10
+ .then(() => {
11
+ console.log('✓ Successfully exported: vo_intro_text_3_trimmed.mp3');
12
+ })
13
+ .catch((error) => {
14
+ console.error('Error during audio processing:', error);
15
+ });
16
+
17
+ // Example 2: Trim silence with padding (200ms at start, 300ms at end)
18
+ console.log('\nExample 2: Trimming with padding...');
19
+ const sfx2 = new SfxMix();
20
+ await sfx2
21
+ .add('part1.mp3')
22
+ .trim({
23
+ paddingStart: 100, // 100ms of silence at the start
24
+ paddingEnd: 100 // 100ms of silence at the end
25
+ })
26
+ .save('part1_trimmed_padded.mp3')
27
+ .then(() => {
28
+ console.log('✓ Successfully exported: vo_intro_text_3_trimmed_padded.mp3');
29
+ })
30
+ .catch((error) => {
31
+ console.error('Error during audio processing:', error);
32
+ });
33
+
@@ -0,0 +1,12 @@
1
+ {
2
+ "name": "demo",
3
+ "version": "1.0.0",
4
+ "description": "",
5
+ "license": "ISC",
6
+ "author": "",
7
+ "type": "module",
8
+ "main": "demo_1.js",
9
+ "scripts": {
10
+ "test": "echo \"Error: no test specified\" && exit 1"
11
+ }
12
+ }
package/demo/part1.mp3 CHANGED
Binary file
package/index.js CHANGED
@@ -51,6 +51,11 @@ class SfxMix {
51
51
  return this;
52
52
  }
53
53
 
54
+ trim(options = {}) {
55
+ this.actions.push({ type: 'trim', options });
56
+ return this;
57
+ }
58
+
54
59
 
55
60
 
56
61
  convertAudio(inputFile, outputFile, outputOptions = {}) {
@@ -161,6 +166,16 @@ class SfxMix {
161
166
  fs.unlinkSync(this.currentFile);
162
167
  }
163
168
  this.currentFile = tempFile;
169
+ } else if (action.type === 'trim') {
170
+ if (this.currentFile == null) {
171
+ throw new Error('No audio to trim. Add audio before trimming.');
172
+ }
173
+ const tempFile = path.join(this.TMP_DIR, `temp_trim_${uuidv4()}.mp3`);
174
+ await this.applyTrim(this.currentFile, action.options, tempFile);
175
+ if (this.isTempFile(this.currentFile)) {
176
+ fs.unlinkSync(this.currentFile);
177
+ }
178
+ this.currentFile = tempFile;
164
179
  }
165
180
  }
166
181
 
@@ -224,7 +239,8 @@ class SfxMix {
224
239
  filename.includes('temp_concat_') ||
225
240
  filename.includes('temp_mix_') ||
226
241
  filename.includes('temp_silence_') ||
227
- filename.includes('temp_filter_')
242
+ filename.includes('temp_filter_') ||
243
+ filename.includes('temp_trim_')
228
244
  );
229
245
  }
230
246
 
@@ -399,6 +415,81 @@ class SfxMix {
399
415
  });
400
416
  }
401
417
 
418
+ applyTrim(inputFile, options, outputFile) {
419
+ return new Promise(async (resolve, reject) => {
420
+ try {
421
+ // Default options for silenceremove filter
422
+ // start_periods: number of silence periods at start to remove (1 = remove silence from start)
423
+ // start_duration: minimum duration of silence to detect at start (in seconds)
424
+ // start_threshold: noise tolerance for start (in dB, e.g., -50dB)
425
+ // stop_periods: number of silence periods at end to remove (-1 = remove all silence from end)
426
+ // stop_duration: minimum duration of silence to detect at end (in seconds)
427
+ // stop_threshold: noise tolerance for end (in dB)
428
+ // paddingStart: milliseconds of silence to add at the start (after removing silence)
429
+ // paddingEnd: milliseconds of silence to add at the end (after removing silence)
430
+
431
+ const startPeriods = options.startPeriods !== undefined ? options.startPeriods : 1;
432
+ const startDuration = options.startDuration !== undefined ? options.startDuration : 0;
433
+ const startThreshold = options.startThreshold !== undefined ? options.startThreshold : -50;
434
+ const stopPeriods = options.stopPeriods !== undefined ? options.stopPeriods : -1;
435
+ const stopDuration = options.stopDuration !== undefined ? options.stopDuration : 0;
436
+ const stopThreshold = options.stopThreshold !== undefined ? options.stopThreshold : -50;
437
+ const paddingStart = options.paddingStart || 0; // in milliseconds
438
+ const paddingEnd = options.paddingEnd || 0; // in milliseconds
439
+
440
+ // Build filter chain
441
+ const filters = [];
442
+
443
+ // Add silenceremove filter
444
+ filters.push(`silenceremove=start_periods=${startPeriods}:start_duration=${startDuration}:start_threshold=${startThreshold}dB:stop_periods=${stopPeriods}:stop_duration=${stopDuration}:stop_threshold=${stopThreshold}dB`);
445
+
446
+ // Add padding at start if specified
447
+ if (paddingStart > 0) {
448
+ filters.push(`adelay=${paddingStart}|${paddingStart}`);
449
+ }
450
+
451
+ // Add padding at end if specified
452
+ if (paddingEnd > 0) {
453
+ const paddingSec = paddingEnd / 1000;
454
+ filters.push(`apad=pad_dur=${paddingSec}`);
455
+ }
456
+
457
+ const filterChain = filters.join(',');
458
+
459
+ let bitrateKbps;
460
+
461
+ // If bitrate is null, auto-detect from input file
462
+ if (this.bitrate === null) {
463
+ let audioInfo = null;
464
+ try {
465
+ audioInfo = await this.getAudioInfo(inputFile);
466
+ } catch (err) {
467
+ console.warn('Could not get audio info for trim, using 128k default:', err.message);
468
+ }
469
+ bitrateKbps = audioInfo ? Math.floor(audioInfo.bitrate / 1000) + 'k' : '128k';
470
+ } else {
471
+ // Use configured default bitrate
472
+ bitrateKbps = Math.floor(this.bitrate / 1000) + 'k';
473
+ }
474
+
475
+ const command = ffmpeg()
476
+ .input(inputFile)
477
+ .audioFilters(filterChain)
478
+ .audioCodec('libmp3lame')
479
+ .audioBitrate(bitrateKbps)
480
+ .format('mp3')
481
+ .output(outputFile);
482
+
483
+ command
484
+ .on('end', () => resolve())
485
+ .on('error', (err) => reject(err))
486
+ .run();
487
+ } catch (err) {
488
+ reject(err);
489
+ }
490
+ });
491
+ }
492
+
402
493
  getFilterChain(filterName, options) {
403
494
  switch (filterName) {
404
495
  case 'normalize':
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "sfxmix",
3
3
  "description": "🎧 SfxMix - Powerful and easy-to-use module for processing audio.",
4
- "version": "1.3.0",
4
+ "version": "1.3.2",
5
5
  "main": "index.js",
6
6
  "dependencies": {
7
7
  "fluent-ffmpeg": "^2.1.3",
@@ -29,6 +29,7 @@
29
29
  "phaser",
30
30
  "compressor",
31
31
  "flanger",
32
+ "trim",
32
33
  "reverb",
33
34
  "highpass",
34
35
  "lowpass",
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes