一、概述
本文简述 FFmpeg
af_sidechaincompress(acompressor)
的使用。
二、Ccompressor 的作用及基本原理
压缩器主要用于减小信号的动态范围。尤其是现代音乐大多采用高比例压缩以提高整体响度。这样做是为了引起听众的最高关注,“丰富”声音并为曲目带来更多“力量”。如果信号被压缩太多,之后听起来可能会沉闷或“死气沉沉”,或者可能会开始“泵动(pump)”(这可能是一个强大的效果,但也可能完全破坏轨道)。正确的压缩是获得专业声音的关键,也是混音和母带处理的高雅艺术。由于其复杂的设置,可能需要很长时间才能获得这种效果的正确感觉。
《搞不懂后期制作的COMPRESSOR压缩效果器?看这篇就对了!》这篇文章进行了比较细致的描述。
除了 FFmpeg,Adobe Audtion
和 Waves
的 Renaissance Vox Vocal Compressor Plugin
($79)等 VST 插件也能很好地实现。
四、在调用 ffmpeg 程序时使用 acompressor
1
| ffmpeg -i input.mp3 -af "acompressor=threshold=-18dB:ratio=8:attack=1:release=100:makeup=1" output.mp3 -y
|
备注:makeup 单位不是 dB。
五、配合 dynaudnorm 标准化
1
| ffmpeg -i input.mp3 -af "acompressor=threshold=-18dB:ratio=8:attack=1:release=100:makeup=1,dynaudnorm=framelen=20:gausssize=13:peak=0.98:threshold=-40dB" output.mp3 -y
|
dynaudnorm
不是本文的重点,在此暂时不用深入了解。详情可见官方文档:https://ffmpeg.org/ffmpeg-filters.html#dynaudnorm
六、在 C# 使用 acompressor
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| public static class CompressUtils { public static async Task<bool> Compress(Stream inputStream, Stream outputStream, int inputSampleRate = 44100, int inputChannels = 2, int inputBitsPreSample = 16, int outputSampleRate = 44100, int ouputChannels = 2, int outputBitsPreSample = 16) { var filters = $"-filter_complex \"acompressor=threshold=-18dB:ratio=8:attack=1:release=100:makeup=1,dynaudnorm=framelen=20:gausssize=13:peak=0.98:threshold=-40dB\""; var fFMpegArguments = FFMpegArguments .FromPipeInput(new StreamPipeSource(inputStream), args => { args.WithCustomArgument("-f s16be -ac 2 -ar 44100 -acodec pcm_s16le"); }); var processor = fFMpegArguments .WithGlobalOptions(options => { options.WithVerbosityLevel(VerbosityLevel.Warning); }) .OutputToPipe(new StreamPipeSink(outputStream), args => { args.WithCustomArgument(filters); if (outputBitsPreSample == 16) { args.WithCustomArgument("-acodec pcm_s16le -f s16le"); } else if (outputBitsPreSample == 32) { args.WithCustomArgument("-acodec pcm_f32le -f f32le"); } else { throw new NotSupportedException("只支持转换为 s16le 和 f32le 。"); } args.WithAudioSamplingRate(outputSampleRate) .WithCustomArgument($"-ac {ouputChannels}"); });
var arguments = processor.Arguments;
return await processor.ProcessAsynchronously(true, Contracts.DefaultFFOptions) .ConfigureAwait(false); } }
|
主要使用了 FFMpegCore,因为它将命名管道进行了封装以支持 Stream 到 Stream 的输入和输出。
参考资料