SfxMix Audio Processing
Instructions
Preserve Audio Quality
Keep intermediate processing lossless. Pipeline steps should write temporary audio as WAV PCM unless the user is explicitly exporting to a compressed final format such as MP3 or OGG.
Compression belongs at the final save() boundary. Do not add MP3 encoding inside actions such as concat, mix, silence generation, filters, trim, or chunk splitting.
Match the Fluent API
Public methods should be chainable and return this. Add work to this.actions, then implement the actual processing in _processActions().
Use domain names that describe the audio behavior. For silence-detected sound segments, use chunk terminology:
sfx
.add('input.wav')
.split({ chunk: 1 })
.save('second_chunk.wav');
split() Defaults
The default chunk splitting options are:
{
chunk: 0,
threshold: -35,
silenceDuration: 0.03,
paddingStart: 0,
paddingEnd: 30,
minDuration: 0.01
}
chunk is zero-based. chunk: 0 keeps the first detected non-silent segment; chunk: 1 keeps the second.
Function Reference
Use README.md as the user-facing source for API examples and docs. When changing a public method or filter, keep this reference, README.md, and index.js aligned.
Public API
constructor(config = {}): Initializes an action queue, current file state, output bitrate, and a unique temp directory. config.bitrate defaults to 64000; use null to let FFmpeg choose. config.tmpDir overrides the OS temp base.
add(input): Queues an audio file for concatenation. Returns this.
mix(input, options = {}): Queues a mix against the current audio. If called first, it behaves like add(input). options.duration supports 'longest', 'shortest', or 'first'; default is 'longest'. Returns this.
silence(milliseconds): Queues generated silence in milliseconds. Returns this.
filter(filterName, options = {}): Queues a named FFmpeg audio filter. Returns this.
trim(options = {}): Queues leading/trailing silence trimming while preserving internal silence. Defaults: startDuration: 0, startThreshold: -30, stopDuration: 0.05, stopThreshold: -30, paddingStart: 0, paddingEnd: 0. Returns this.
split(options = {}): Queues extraction of one silence-detected non-silent chunk. Defaults are listed above. Returns this.
keep(segments, options = {}): Queues retention of arbitrary { start, end } ranges in seconds. Discards audio outside those ranges. Options: joinPadMs (default 0), fadeMs (default 0). Segments must not overlap; order in the input array does not matter. Returns this.
cut(segments, options = {}): Queues removal of arbitrary { start, end } ranges in seconds, keeping the complement. Options mirror keep: joinPadMs (default 0), fadeMs (default 0). Segments must not overlap; order in the input array does not matter. Returns this.
normalize(tp = -1.5): Convenience wrapper for filter('normalize', { tp }). Returns this.
peakNormalize(targetDb = -3): Queues sample peak normalization to a dBFS ceiling. Measures max_volume with FFmpeg volumedetect, then applies calculated gain with the volume filter. Returns this.
save(output, outputOptions = {}): Processes queued actions, writes the final output, resets the instance, and resolves with the absolute output path. Custom outputOptions are passed to convertAudio().
isTruncated(options = {}): Terminal analysis operation. Processes queued actions, checks whether the audio tail is above options.threshold, resets the instance, and resolves { truncated, tailRmsDb, tailPeakDb, duration, threshold, tailDuration }. Defaults: tailDuration: 50, threshold: -30.
reset(): Clears queued actions and current file state. Returns this.
Conversion Helpers
convertAudio(inputFile, outputFile, outputOptions = {}): Converts audio to the requested output path. Without custom options, chooses codec/format from the extension: OGG/Opus, WAV/PCM, FLAC, AAC/M4A, or MP3/libmp3lame.
convertToOgg(inputFile, outputFile, options = {}): Backward-compatible alias for convertAudio().
Supported Filters
normalize: EBU R128 loudness normalization. Options: i, lra, tp.
telephone: High-pass plus low-pass telephone effect. Options: lowFreq, highFreq.
echo: FFmpeg aecho. Options: inGain, outGain, delays, decays.
highpass: Requires frequency.
lowpass: Requires frequency.
volume: Requires volume.
equalizer: Requires frequency, width, and gain.
flanger: Options: delay, depth, regen, width, speed, shape, phase, interp.
pitch: Requires pitch in semitones.
tremolo: Options: frequency.
phaser: Options: in_gain, out_gain, delay, decay, speed, type.
tempo: Requires x. Values outside FFmpeg's single-filter 0.5 to 2.0 range are split into chained atempo filters.
Internal Processing Helpers
getTempFile(prefix, extension = 'wav'): Builds unique temp file paths inside the instance temp directory.
applyIntermediateOutput(command, outputFile): Forces intermediate FFmpeg output to WAV PCM.
cleanup(): Removes the instance temp directory.
_processActions(): Runs queued add, mix, silence, filter, trim, split, keep, and cut actions in order.
safeDeleteFile(filePath, maxRetries = 3): Deletes temp files with retry backoff.
isTempFile(filename): Checks whether a path belongs to the instance temp directory.
concatenateAudioFiles(inputFiles, outputFile): Concatenates files with FFmpeg's concat filter.
mixAudioFiles(inputFile1, inputFile2, outputFile, options = {}): Mixes two inputs with FFmpeg's amix.
_analyzeTail(filePath, options = {}): Reads the tail as PCM samples and computes RMS/peak dB metrics.
getAudioInfo(inputFile): Reads channel count, sample rate, and bitrate through ffprobe.
generateSilence(durationMs, outputFile, audioInfo = null): Generates PCM silence matching provided audio metadata when available.
applyFilter(inputFile, filterName, options, outputFile): Resolves a filter chain and writes a filtered intermediate WAV.
getMaxVolume(inputFile): Measures sample peak dBFS using FFmpeg volumedetect.
applyPeakNormalize(inputFile, targetDb, outputFile): Applies calculated dB gain so the measured sample peak reaches targetDb.
applyTrim(inputFile, options, outputFile): Applies leading/trailing silence removal.
applySplit(inputFile, options, outputFile): Detects silence boundaries and extracts the requested chunk.
validateKeepSegments(inputFile, segments): Validates keep ranges and returns sorted segments.
applyKeep(inputFile, segments, options, outputFile): Extracts and concatenates kept ranges via FFmpeg atrim/concat.
getComplementSegments(orderedRanges, duration): Builds the complement of sorted cut ranges.
applyCut(inputFile, segments, options, outputFile): Converts cut ranges to keep ranges and delegates processing to applyKeep.
getAudioDuration(inputFile): Reads duration through ffprobe.
parseSilenceEvent(line): Parses FFmpeg silencedetect stderr lines.
detectSilence(inputFile, options = {}): Runs silencedetect and returns ordered silence events.
getNonSilentSegments(silenceEvents, duration, minDuration = 0.01): Converts silence events into non-silent segments.
getFilterChain(filterName, options): Maps supported filter names and options to FFmpeg filter strings.
1---2name: sfxmix3description: Guidance for working on the SfxMix audio processing library. Use when modifying SfxMix APIs, FFmpeg processing steps, demo audio scripts, chunk splitting, silence detection, or README examples for this project.4---56# SfxMix Audio Processing78## Instructions910### Preserve Audio Quality1112Keep intermediate processing lossless. Pipeline steps should write temporary audio as WAV PCM unless the user is explicitly exporting to a compressed final format such as MP3 or OGG.1314Compression belongs at the final `save()` boundary. Do not add MP3 encoding inside actions such as concat, mix, silence generation, filters, trim, or chunk splitting.1516### Match the Fluent API1718Public methods should be chainable and return `this`. Add work to `this.actions`, then implement the actual processing in `_processActions()`.1920Use domain names that describe the audio behavior. For silence-detected sound segments, use `chunk` terminology:2122```js23sfx24 .add('input.wav')25 .split({ chunk: 1 })26 .save('second_chunk.wav');27```2829### `split()` Defaults3031The default chunk splitting options are:3233```js34{35 chunk: 0,36 threshold: -35,37 silenceDuration: 0.03,38 paddingStart: 0,39 paddingEnd: 30,40 minDuration: 0.0141}42```4344`chunk` is zero-based. `chunk: 0` keeps the first detected non-silent segment; `chunk: 1` keeps the second.4546## Function Reference4748Use `README.md` as the user-facing source for API examples and docs. When changing a public method or filter, keep this reference, `README.md`, and `index.js` aligned.4950### Public API5152- `constructor(config = {})`: Initializes an action queue, current file state, output bitrate, and a unique temp directory. `config.bitrate` defaults to `64000`; use `null` to let FFmpeg choose. `config.tmpDir` overrides the OS temp base.53- `add(input)`: Queues an audio file for concatenation. Returns `this`.54- `mix(input, options = {})`: Queues a mix against the current audio. If called first, it behaves like `add(input)`. `options.duration` supports `'longest'`, `'shortest'`, or `'first'`; default is `'longest'`. Returns `this`.55- `silence(milliseconds)`: Queues generated silence in milliseconds. Returns `this`.56- `filter(filterName, options = {})`: Queues a named FFmpeg audio filter. Returns `this`.57- `trim(options = {})`: Queues leading/trailing silence trimming while preserving internal silence. Defaults: `startDuration: 0`, `startThreshold: -30`, `stopDuration: 0.05`, `stopThreshold: -30`, `paddingStart: 0`, `paddingEnd: 0`. Returns `this`.58- `split(options = {})`: Queues extraction of one silence-detected non-silent chunk. Defaults are listed above. Returns `this`.59- `keep(segments, options = {})`: Queues retention of arbitrary `{ start, end }` ranges in seconds. Discards audio outside those ranges. Options: `joinPadMs` (default `0`), `fadeMs` (default `0`). Segments must not overlap; order in the input array does not matter. Returns `this`.60- `cut(segments, options = {})`: Queues removal of arbitrary `{ start, end }` ranges in seconds, keeping the complement. Options mirror `keep`: `joinPadMs` (default `0`), `fadeMs` (default `0`). Segments must not overlap; order in the input array does not matter. Returns `this`.61- `normalize(tp = -1.5)`: Convenience wrapper for `filter('normalize', { tp })`. Returns `this`.62- `peakNormalize(targetDb = -3)`: Queues sample peak normalization to a dBFS ceiling. Measures `max_volume` with FFmpeg `volumedetect`, then applies calculated gain with the `volume` filter. Returns `this`.63- `save(output, outputOptions = {})`: Processes queued actions, writes the final output, resets the instance, and resolves with the absolute output path. Custom `outputOptions` are passed to `convertAudio()`.64- `isTruncated(options = {})`: Terminal analysis operation. Processes queued actions, checks whether the audio tail is above `options.threshold`, resets the instance, and resolves `{ truncated, tailRmsDb, tailPeakDb, duration, threshold, tailDuration }`. Defaults: `tailDuration: 50`, `threshold: -30`.65- `reset()`: Clears queued actions and current file state. Returns `this`.6667### Conversion Helpers6869- `convertAudio(inputFile, outputFile, outputOptions = {})`: Converts audio to the requested output path. Without custom options, chooses codec/format from the extension: OGG/Opus, WAV/PCM, FLAC, AAC/M4A, or MP3/libmp3lame.70- `convertToOgg(inputFile, outputFile, options = {})`: Backward-compatible alias for `convertAudio()`.7172### Supported Filters7374- `normalize`: EBU R128 loudness normalization. Options: `i`, `lra`, `tp`.75- `telephone`: High-pass plus low-pass telephone effect. Options: `lowFreq`, `highFreq`.76- `echo`: FFmpeg `aecho`. Options: `inGain`, `outGain`, `delays`, `decays`.77- `highpass`: Requires `frequency`.78- `lowpass`: Requires `frequency`.79- `volume`: Requires `volume`.80- `equalizer`: Requires `frequency`, `width`, and `gain`.81- `flanger`: Options: `delay`, `depth`, `regen`, `width`, `speed`, `shape`, `phase`, `interp`.82- `pitch`: Requires `pitch` in semitones.83- `tremolo`: Options: `frequency`.84- `phaser`: Options: `in_gain`, `out_gain`, `delay`, `decay`, `speed`, `type`.85- `tempo`: Requires `x`. Values outside FFmpeg's single-filter `0.5` to `2.0` range are split into chained `atempo` filters.8687### Internal Processing Helpers8889- `getTempFile(prefix, extension = 'wav')`: Builds unique temp file paths inside the instance temp directory.90- `applyIntermediateOutput(command, outputFile)`: Forces intermediate FFmpeg output to WAV PCM.91- `cleanup()`: Removes the instance temp directory.92- `_processActions()`: Runs queued `add`, `mix`, `silence`, `filter`, `trim`, `split`, `keep`, and `cut` actions in order.93- `safeDeleteFile(filePath, maxRetries = 3)`: Deletes temp files with retry backoff.94- `isTempFile(filename)`: Checks whether a path belongs to the instance temp directory.95- `concatenateAudioFiles(inputFiles, outputFile)`: Concatenates files with FFmpeg's `concat` filter.96- `mixAudioFiles(inputFile1, inputFile2, outputFile, options = {})`: Mixes two inputs with FFmpeg's `amix`.97- `_analyzeTail(filePath, options = {})`: Reads the tail as PCM samples and computes RMS/peak dB metrics.98- `getAudioInfo(inputFile)`: Reads channel count, sample rate, and bitrate through `ffprobe`.99- `generateSilence(durationMs, outputFile, audioInfo = null)`: Generates PCM silence matching provided audio metadata when available.100- `applyFilter(inputFile, filterName, options, outputFile)`: Resolves a filter chain and writes a filtered intermediate WAV.101- `getMaxVolume(inputFile)`: Measures sample peak dBFS using FFmpeg `volumedetect`.102- `applyPeakNormalize(inputFile, targetDb, outputFile)`: Applies calculated dB gain so the measured sample peak reaches `targetDb`.103- `applyTrim(inputFile, options, outputFile)`: Applies leading/trailing silence removal.104- `applySplit(inputFile, options, outputFile)`: Detects silence boundaries and extracts the requested chunk.105- `validateKeepSegments(inputFile, segments)`: Validates keep ranges and returns sorted segments.106- `applyKeep(inputFile, segments, options, outputFile)`: Extracts and concatenates kept ranges via FFmpeg `atrim`/`concat`.107- `getComplementSegments(orderedRanges, duration)`: Builds the complement of sorted cut ranges.108- `applyCut(inputFile, segments, options, outputFile)`: Converts cut ranges to keep ranges and delegates processing to `applyKeep`.109- `getAudioDuration(inputFile)`: Reads duration through `ffprobe`.110- `parseSilenceEvent(line)`: Parses FFmpeg `silencedetect` stderr lines.111- `detectSilence(inputFile, options = {})`: Runs `silencedetect` and returns ordered silence events.112- `getNonSilentSegments(silenceEvents, duration, minDuration = 0.01)`: Converts silence events into non-silent segments.113- `getFilterChain(filterName, options)`: Maps supported filter names and options to FFmpeg filter strings.