/** * Audio mixing chain — EQ, compressor, gate, reverb, de-esser, limiter. * * File-only path: pure ffmpeg filter strings, mirroring `audio-cleanup.ts` * but with parameter knobs the agent can tune per-clip. We expose this as * a single "chain" so the agent can express a full mixing decision in one * call (e.g. "vocal preset = highpass 80Hz + 3dB peak at 5kHz + 4:1 comp + * -1dB ceiling limiter"). * * All filters confirmed present in stock Homebrew ffmpeg: * - equalizer / highpass / lowpass — eq bands * - acompressor — compressor * - agate — gate * - aecho / aphaser — pseudo-reverb * - alimiter — brick-wall limiter * - adynamicequalizer — de-esser (5-9 kHz dynamic shelf) * * Real-world reference for filter syntax: ffmpeg-filters man page + * jiaaro/pydub's effect chains + scottcjn/bottube's mixing helpers. */ export interface EqBand { /** Filter type. */ type: "low" | "high" | "peak" | "shelf-low" | "shelf-high"; /** Center / cutoff frequency in Hz. */ freqHz: number; /** Gain in dB (peak / shelf only; ignored for low/high pass). */ gainDb?: number; /** Bandwidth Q-factor. Default 1. Higher = narrower band. */ q?: number; } export interface Compressor { /** Threshold in dB below which the comp doesn't act. -18 to -10 typical for voice. */ thresholdDb: number; /** Ratio. 4 = 4:1 = strong voice control. */ ratio: number; /** Attack in ms. Default 20. */ attackMs?: number; /** Release in ms. Default 250. */ releaseMs?: number; /** Makeup gain in dB. Default 0. */ makeupDb?: number; } export interface Gate { /** Below threshold the signal is attenuated. -50 dB cuts most room tone. */ thresholdDb: number; /** Ratio. Higher = more aggressive cut. Default 5. */ ratio?: number; attackMs?: number; releaseMs?: number; } export interface Reverb { /** 0..1; how big the room sounds. */ roomSize: number; /** 0..1; balance. 0 = dry, 1 = all wet. */ wetDryMix: number; } export interface Limiter { /** Output ceiling in dB. -1 dBTP is the YouTube/Spotify-friendly default. */ ceilingDb: number; releaseMs?: number; } export interface DeEsser { /** Frequency in Hz where sibilance lives. Default 6500. */ freqHz?: number; /** Threshold in dB above which the dynamic shelf engages. Default -25. */ thresholdDb?: number; } export interface AudioChain { eq?: EqBand[]; compressor?: Compressor; gate?: Gate; reverb?: Reverb; deess?: DeEsser; limiter?: Limiter; } /** * Build the ffmpeg `-af` filter string for a chain. Pure function — tests * verify the full string assembly without spawning ffmpeg. * * Order: gate → eq → de-esser → compressor → reverb → limiter. This matches * the conventional mixing console order: clean noise out first, shape tone, * tame dynamics, add ambience, then catch peaks. */ export declare function buildMixFilter(chain: AudioChain): string; /** Apply a mixing chain to one input file. Video stream is copied. */ export declare function applyMix(inputPath: string, outputPath: string, chain: AudioChain, opts?: { signal?: AbortSignal; }): Promise; //# sourceMappingURL=audio-mix.d.ts.map