From 39a44c3735e45558a33d73aeeaaf9a366d2e2c37 Mon Sep 17 00:00:00 2001 From: aNNiMON Date: Sun, 15 Sep 2024 23:19:58 +0300 Subject: [PATCH] Add audio compressor --- README.md | 3 +- .../commands/ffmpeg/FFmpegCommandBuilder.java | 24 ++++++++ .../ffmpegbot/commands/ffmpeg/Visitor.java | 1 + .../ffmpegbot/parameters/AudioCompressor.java | 60 +++++++++++++++++++ .../parameters/resolvers/AudioResolver.java | 2 + 5 files changed, 89 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/annimon/ffmpegbot/parameters/AudioCompressor.java diff --git a/README.md b/README.md index aeed6af..0a9ecd5 100644 --- a/README.md +++ b/README.md @@ -6,9 +6,10 @@ Telegram Bot for re-encoding media - change a video resolution, bitrate, frame rate, speed - change an audio bitrate, volume, pitch - - apply audio effects + - apply audio effects, compressor - extract or remove audio from the video - resend video note as a regular video, or video as an audio track + - output audio spectrum for quick analysis ## Requirements diff --git a/src/main/java/com/annimon/ffmpegbot/commands/ffmpeg/FFmpegCommandBuilder.java b/src/main/java/com/annimon/ffmpegbot/commands/ffmpeg/FFmpegCommandBuilder.java index 9411ec7..6bfb28a 100644 --- a/src/main/java/com/annimon/ffmpegbot/commands/ffmpeg/FFmpegCommandBuilder.java +++ b/src/main/java/com/annimon/ffmpegbot/commands/ffmpeg/FFmpegCommandBuilder.java @@ -49,6 +49,30 @@ public class FFmpegCommandBuilder implements Visitor { audioCommands.add(p.getValue()); } + @Override + public void visit(AudioCompressor p, MediaSession input) { + if (discardAudio) return; + if (p.getValue().isEmpty()) return; + audioFilters.add(switch (p.getValue()) { + case AudioCompressor.COMP_2_6DB -> "compand=points=-80/-80|-6/-6|0/-3.8|20/3.5"; + case AudioCompressor.COMP_2_12DB -> "compand=points=-80/-80|-12/-12|0/-6.8|20/1.9"; + case AudioCompressor.COMP_2_18DB -> "compand=points=-80/-80|-18/-18|0/-9.8|20/0.7"; + case AudioCompressor.COMP_3_9DB -> "compand=points=-80/-80|-9/-9|0/-3.8|20/-2.1"; + case AudioCompressor.COMP_3_18DB -> "compand=points=-80/-80|-18/-18|0/-6.8|20/-4.5"; + case AudioCompressor.COMP_NORMALIZE_1 -> "compand=.3|.3:1|1:-90/-60|-60/-40|-40/-30|-20/-20:6:0:-90:0.2"; + case AudioCompressor.COMP_NORMALIZE_2 -> "compand=0|0:1|1:-90/-900|-70/-70|-30/-9|0/-3:6:0:0:0"; + case AudioCompressor.COMP_NOISE_GATE_1 -> "compand=points=-80/-900|-45/-15|-27/-9|0/-7|20/-7:attacks=0"; + case AudioCompressor.COMP_NOISE_GATE_2 -> "compand=.1|.1:.2|.2:-900/-900|-50.1/-900|-50/-50:.01:0:-90:.1"; + case AudioCompressor.COMP_HARD_LIMITER_6DB -> "compand=attacks=0:points=-80/-80|-6/-6|20/-6"; + case AudioCompressor.COMP_HARD_LIMITER_12DB -> "compand=attacks=0:points=-80/-80|-12/-12|20/-12"; + case AudioCompressor.COMP_HARD_NOISE_GATE_35DB -> "compand=attacks=0:points=-80/-115|-35.1/-80|-35/-35|20/20"; + case AudioCompressor.COMP_SOFT_LIMITER -> "compand=attacks=0:points=-80/-80|-12.4/-12.4|-6/-8|0/-6.8|20/-2.8"; + case AudioCompressor.COMP_EXPANDER -> "compand=attacks=0:points=-80/-169|-54/-80|-49.5/-64.6|-41.1/-41.1|-25.8/-15|-10.8/-4.5|0/0|20/8.3"; + case AudioCompressor.COMP_GATE -> "compand=points=-80/-105|-62/-80|-15.4/-15.4|0/-12|20/-7.6"; + default -> "compand"; + }); + } + @Override public void visit(AudioCrystalizer p, MediaSession input) { if (discardAudio) return; diff --git a/src/main/java/com/annimon/ffmpegbot/commands/ffmpeg/Visitor.java b/src/main/java/com/annimon/ffmpegbot/commands/ffmpeg/Visitor.java index 1f07033..e4ebeab 100644 --- a/src/main/java/com/annimon/ffmpegbot/commands/ffmpeg/Visitor.java +++ b/src/main/java/com/annimon/ffmpegbot/commands/ffmpeg/Visitor.java @@ -5,6 +5,7 @@ import com.annimon.ffmpegbot.parameters.*; public interface Visitor { void visit(DisableAudio p, I input); void visit(AudioBitrate p, I input); + void visit(AudioCompressor p, I input); void visit(AudioCrystalizer p, I input); void visit(AudioEffect p, I input); void visit(AudioPitch p, I input); diff --git a/src/main/java/com/annimon/ffmpegbot/parameters/AudioCompressor.java b/src/main/java/com/annimon/ffmpegbot/parameters/AudioCompressor.java new file mode 100644 index 0000000..cb38452 --- /dev/null +++ b/src/main/java/com/annimon/ffmpegbot/parameters/AudioCompressor.java @@ -0,0 +1,60 @@ +package com.annimon.ffmpegbot.parameters; + +import com.annimon.ffmpegbot.commands.ffmpeg.Visitor; +import java.util.List; + +public class AudioCompressor extends StringParameter { + public static final String ID = "acompand"; + + public static final String COMP_DEFAULT = "Default"; + public static final String COMP_2_6DB = "2:1 at -6dB"; + public static final String COMP_2_12DB = "2:1 at -12dB"; + public static final String COMP_2_18DB = "2:1 at -18dB"; + public static final String COMP_3_9DB = "3:1 at -9dB"; + public static final String COMP_3_18DB = "3:1 at -18dB"; + public static final String COMP_NORMALIZE_1 = "Normalize 1"; + public static final String COMP_NORMALIZE_2 = "Normalize 2"; + public static final String COMP_NOISE_GATE_1 = "Noise Gate 1"; + public static final String COMP_NOISE_GATE_2 = "Noise Gate 2"; + public static final String COMP_HARD_NOISE_GATE_35DB = "Noise Gate 35dB"; + public static final String COMP_HARD_LIMITER_6DB = "Hard Limiter -6dB"; + public static final String COMP_HARD_LIMITER_12DB = "Hard Limiter -12dB"; + public static final String COMP_SOFT_LIMITER = "Soft Limiter"; + public static final String COMP_EXPANDER = "Expander"; + public static final String COMP_GATE = "Gate"; + + private static final List VALUES = List.of( + "", COMP_DEFAULT, + COMP_2_6DB, COMP_2_12DB, COMP_2_18DB, + COMP_3_9DB, COMP_3_18DB, + COMP_NORMALIZE_1, COMP_NORMALIZE_2, + COMP_NOISE_GATE_1, COMP_NOISE_GATE_2, + COMP_HARD_NOISE_GATE_35DB, + COMP_HARD_LIMITER_6DB, COMP_HARD_LIMITER_12DB, + COMP_SOFT_LIMITER, + COMP_EXPANDER, COMP_GATE + ); + + public AudioCompressor() { + super(ID, "\uD83D\uDD08 Compressor", VALUES, ""); + } + + @Override + public String describeValue(String value) { + if (value.isEmpty()) { + return "NONE"; + } else { + return super.describeValue(value); + } + } + + @Override + public int defaultColumnsCount() { + return 3; + } + + @Override + public void accept(Visitor visitor, I input) { + visitor.visit(this, input); + } +} diff --git a/src/main/java/com/annimon/ffmpegbot/parameters/resolvers/AudioResolver.java b/src/main/java/com/annimon/ffmpegbot/parameters/resolvers/AudioResolver.java index e31cec0..b8a8a9f 100644 --- a/src/main/java/com/annimon/ffmpegbot/parameters/resolvers/AudioResolver.java +++ b/src/main/java/com/annimon/ffmpegbot/parameters/resolvers/AudioResolver.java @@ -22,6 +22,7 @@ public class AudioResolver implements ParametersResolver { disableAudioParam(parameters, fileInfo.fileType()); parameters.addAll(List.of( new AudioBitrate(), + new AudioCompressor(), new AudioCrystalizer(), new AudioEffect(), new AudioPitch(), @@ -36,6 +37,7 @@ public class AudioResolver implements ParametersResolver { .ifPresent(p -> { final Set parameterIds = Set.of( AudioBitrate.ID, + AudioCompressor.ID, AudioCrystalizer.ID, AudioEffect.ID, AudioPitch.ID,