PR #25064 opened by Niklas Haas (haasn) URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25064 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25064.patch
The old peak-based detection mode works well for digital silence, but basically nothing else. The slightest rustle, wind noise or other transient will disturb the detection. Using a BS.1770-gated loudness average gives much more accurate results at distinguishing between real content (e.g. speech) and real silence across a diverse set of test samples. >From 0135d3bfd6f537629d3c176ff589e162e0693e17 Mon Sep 17 00:00:00 2001 From: Niklas Haas <[email protected]> Date: Mon, 14 Sep 2026 15:28:19 +0200 Subject: [PATCH 1/4] Revert "avfilter/ebur128: Remove unused functions" This partially reverts commit ba874ad904042d0f90e392f45560b170e05512a6. Needed for the upcoming commits. Signed-off-by: Niklas Haas <[email protected]> --- libavfilter/ebur128.c | 32 ++++++++++++++++++++++++++++---- libavfilter/ebur128.h | 43 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 70 insertions(+), 5 deletions(-) diff --git a/libavfilter/ebur128.c b/libavfilter/ebur128.c index 062099e206..1cb6309b71 100644 --- a/libavfilter/ebur128.c +++ b/libavfilter/ebur128.c @@ -363,6 +363,9 @@ static void ebur128_filter_##type(FFEBUR128State* st, const type** srcs, st->d->v[ci][1] = fabs(st->d->v[ci][1]) < DBL_MIN ? 0.0 : st->d->v[ci][1]; \ } \ } +EBUR128_FILTER(short, -((double)SHRT_MIN)) +EBUR128_FILTER(int, -((double)INT_MIN)) +EBUR128_FILTER(float, 1.0) EBUR128_FILTER(double, 1.0) static double ebur128_energy_to_loudness(double energy) @@ -457,8 +460,8 @@ int ff_ebur128_set_channel(FFEBUR128State * st, } static int ebur128_energy_shortterm(FFEBUR128State * st, double *out); -#define EBUR128_ADD_FRAMES_PLANAR(type) \ -static void ebur128_add_frames_planar_##type(FFEBUR128State* st, const type** srcs, \ +#define FF_EBUR128_ADD_FRAMES_PLANAR(type) \ +void ff_ebur128_add_frames_planar_##type(FFEBUR128State* st, const type** srcs, \ size_t frames, int stride) { \ size_t src_index = 0; \ while (frames > 0) { \ @@ -500,7 +503,10 @@ static void ebur128_add_frames_planar_##type(FFEBUR128State* st, const type** sr } \ } \ } -EBUR128_ADD_FRAMES_PLANAR(double) +FF_EBUR128_ADD_FRAMES_PLANAR(short) +FF_EBUR128_ADD_FRAMES_PLANAR(int) +FF_EBUR128_ADD_FRAMES_PLANAR(float) +FF_EBUR128_ADD_FRAMES_PLANAR(double) #define FF_EBUR128_ADD_FRAMES(type) \ void ff_ebur128_add_frames_##type(FFEBUR128State* st, const type* src, \ size_t frames) { \ @@ -508,8 +514,11 @@ void ff_ebur128_add_frames_##type(FFEBUR128State* st, const type* src, \ const type **buf = (const type**)st->d->data_ptrs; \ for (i = 0; i < st->channels; i++) \ buf[i] = src + i; \ - ebur128_add_frames_planar_##type(st, buf, frames, st->channels); \ + ff_ebur128_add_frames_planar_##type(st, buf, frames, st->channels); \ } +FF_EBUR128_ADD_FRAMES(short) +FF_EBUR128_ADD_FRAMES(int) +FF_EBUR128_ADD_FRAMES(float) FF_EBUR128_ADD_FRAMES(double) static int ebur128_calc_relative_threshold(FFEBUR128State **sts, size_t size, @@ -614,6 +623,21 @@ static int ebur128_energy_shortterm(FFEBUR128State * st, double *out) out); } +int ff_ebur128_loudness_momentary(FFEBUR128State * st, double *out) +{ + double energy; + int error = ebur128_energy_in_interval(st, st->d->samples_in_100ms * 4, + &energy); + if (error) { + return error; + } else if (energy <= 0.0) { + *out = -HUGE_VAL; + return 0; + } + *out = ebur128_energy_to_loudness(energy); + return 0; +} + int ff_ebur128_loudness_shortterm(FFEBUR128State * st, double *out) { double energy; diff --git a/libavfilter/ebur128.h b/libavfilter/ebur128.h index 8e7385e044..830919d1af 100644 --- a/libavfilter/ebur128.h +++ b/libavfilter/ebur128.h @@ -81,7 +81,7 @@ enum channel { * modes that suit your needs, as performance will be better. */ enum mode { - /** can resurrrect and call ff_ebur128_loudness_momentary */ + /** can call ff_ebur128_loudness_momentary */ FF_EBUR128_MODE_M = (1 << 0), /** can call ff_ebur128_loudness_shortterm */ FF_EBUR128_MODE_S = (1 << 1) | FF_EBUR128_MODE_M, @@ -151,9 +151,41 @@ int ff_ebur128_set_channel(FFEBUR128State * st, * @param src array of source frames. Channels must be interleaved. * @param frames number of frames. Not number of samples! */ +void ff_ebur128_add_frames_short(FFEBUR128State * st, + const short *src, size_t frames); +/** \brief See \ref ebur128_add_frames_short */ +void ff_ebur128_add_frames_int(FFEBUR128State * st, + const int *src, size_t frames); +/** \brief See \ref ebur128_add_frames_short */ +void ff_ebur128_add_frames_float(FFEBUR128State * st, + const float *src, size_t frames); +/** \brief See \ref ebur128_add_frames_short */ void ff_ebur128_add_frames_double(FFEBUR128State * st, const double *src, size_t frames); +/** \brief Add frames to be processed. + * + * @param st library state. + * @param srcs array of source frame channel data pointers + * @param frames number of frames. Not number of samples! + * @param stride number of samples to skip to for the next sample of the same channel + */ +void ff_ebur128_add_frames_planar_short(FFEBUR128State * st, + const short **srcs, + size_t frames, int stride); +/** \brief See \ref ebur128_add_frames_planar_short */ +void ff_ebur128_add_frames_planar_int(FFEBUR128State * st, + const int **srcs, + size_t frames, int stride); +/** \brief See \ref ebur128_add_frames_planar_short */ +void ff_ebur128_add_frames_planar_float(FFEBUR128State * st, + const float **srcs, + size_t frames, int stride); +/** \brief See \ref ebur128_add_frames_planar_short */ +void ff_ebur128_add_frames_planar_double(FFEBUR128State * st, + const double **srcs, + size_t frames, int stride); + /** \brief Get global integrated loudness in LUFS. * * @param st library state. @@ -165,6 +197,15 @@ void ff_ebur128_add_frames_double(FFEBUR128State * st, */ int ff_ebur128_loudness_global(FFEBUR128State * st, double *out); +/** \brief Get momentary loudness (last 400ms) in LUFS. + * + * @param st library state. + * @param out momentary loudness in LUFS. -HUGE_VAL if result is negative + * infinity. + * @return + * - 0 on success. + */ +int ff_ebur128_loudness_momentary(FFEBUR128State * st, double *out); /** \brief Get short-term loudness (last 3s) in LUFS. * * @param st library state. -- 2.52.0 >From 8c0bd33f891bdc708aca65be87092884e4a0108d Mon Sep 17 00:00:00 2001 From: Niklas Haas <[email protected]> Date: Mon, 14 Sep 2026 16:06:52 +0200 Subject: [PATCH 2/4] avfilter/ebur128: make ff_ebur128_destroy() safe to call on NULL Signed-off-by: Niklas Haas <[email protected]> --- libavfilter/ebur128.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavfilter/ebur128.c b/libavfilter/ebur128.c index 1cb6309b71..8574364d4e 100644 --- a/libavfilter/ebur128.c +++ b/libavfilter/ebur128.c @@ -303,6 +303,8 @@ exit: void ff_ebur128_destroy(FFEBUR128State ** st) { + if (!(*st)) + return; av_free((*st)->d->block_energy_histogram); av_free((*st)->d->short_term_block_energy_histogram); av_free((*st)->d->audio_data); -- 2.52.0 >From edffd35ecb8ef904548effd0a2095f61023b8754 Mon Sep 17 00:00:00 2001 From: Niklas Haas <[email protected]> Date: Mon, 14 Sep 2026 16:17:17 +0200 Subject: [PATCH 3/4] avfilter/af_silencedetect: add BS.1770 loudness measurement mode This can be a more reliable way to detect content silence than looking at raw sample peaks alone, and will exclude things like isolated glitches or occasional hiss that happens to be mastered above the chosen noise threshold. Because BS.1770 momentary loudness is updated only once every 100ms block, we cache the result of the previous loudness measurement and report that for every sample in the same 100ms window. Signed-off-by: Niklas Haas <[email protected]> --- doc/filters.texi | 18 ++++ libavfilter/Makefile | 2 +- libavfilter/af_silencedetect.c | 175 ++++++++++++++++++++++++++++----- 3 files changed, 170 insertions(+), 25 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 04496d338f..81a2cda3b9 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -6506,6 +6506,18 @@ for the accepted syntax. @item mono, m Process each channel separately, instead of combined. By default is disabled. + +@item mode +Affects how silence is classified. Accepts the following values: +@table @samp +@item peak +Compare the absolute value of each sample to the noise tolerance. This is the +default mode. + +@item loudness +Compare the momentary loudness, as defined by ITU-R BS.1770, to the noise +tolerance in LUFS. +@end table @end table @subsection Examples @@ -6517,6 +6529,12 @@ Detect 5 seconds of silence with -50dB noise tolerance: silencedetect=n=-50dB:d=5 @end example +@item +Detect 2 seconds of silence, with a -35 LUFS noise tolerance: +@example +silencedetect=mode=loudness:n=-35dB:d=2 +@end example + @item Complete example with @command{ffmpeg} to detect silence with 0.0001 noise tolerance in @file{silence.mp3}: diff --git a/libavfilter/Makefile b/libavfilter/Makefile index 15d0b23af9..6b1ad27ef2 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -161,7 +161,7 @@ OBJS-$(CONFIG_REPLAYGAIN_FILTER) += af_replaygain.o OBJS-$(CONFIG_RUBBERBAND_FILTER) += af_rubberband.o OBJS-$(CONFIG_SIDECHAINCOMPRESS_FILTER) += af_sidechaincompress.o OBJS-$(CONFIG_SIDECHAINGATE_FILTER) += af_agate.o -OBJS-$(CONFIG_SILENCEDETECT_FILTER) += af_silencedetect.o +OBJS-$(CONFIG_SILENCEDETECT_FILTER) += af_silencedetect.o ebur128.o OBJS-$(CONFIG_SILENCEREMOVE_FILTER) += af_silenceremove.o OBJS-$(CONFIG_SOFALIZER_FILTER) += af_sofalizer.o OBJS-$(CONFIG_SPEECHNORM_FILTER) += af_speechnorm.o diff --git a/libavfilter/af_silencedetect.c b/libavfilter/af_silencedetect.c index bcdc90f8e3..4b0b8523f7 100644 --- a/libavfilter/af_silencedetect.c +++ b/libavfilter/af_silencedetect.c @@ -24,18 +24,29 @@ */ #include <float.h> /* DBL_MAX */ +#include <math.h> #include "libavutil/mem.h" #include "libavutil/opt.h" #include "libavutil/timestamp.h" #include "audio.h" #include "avfilter.h" +#include "ebur128.h" #include "filters.h" +enum SilenceDetectMode { + MODE_PEAK, + MODE_LOUDNESS, + MODE_NB, +}; + typedef struct SilenceDetectContext { const AVClass *class; + FFEBUR128State **r128; + double noise; ///< noise amplitude ratio int64_t duration; ///< minimum duration of silence until notification + int mode; ///< enum SilenceDetectMode int mono; ///< mono mode : check each channel separately (default = check when ALL channels are silent) int channels; ///< number of channels int independent_channels; ///< number of entries in following arrays (always 1 in mono mode) @@ -44,6 +55,8 @@ typedef struct SilenceDetectContext { int64_t frame_end; ///< pts of the end of the current frame (used to compute duration of silence at EOS) int last_sample_rate; ///< last sample rate to check for sample rate changes AVRational time_base; ///< time_base + int nb_pending_samples; ///< number of samples until loudness is measured + int *is_silence; ///< (array) result of previous loudness measurement void (*silencedetect)(AVFilterContext *ctx, AVFrame *insamples, int nb_samples, int64_t nb_samples_notify, @@ -51,9 +64,14 @@ typedef struct SilenceDetectContext { } SilenceDetectContext; #define MAX_DURATION (24*3600*1000000LL) +#define LOUDNESS_STEP(sample_rate) (((sample_rate) + 5) / 10) /* 100 ms */ +#define LOUDNESS_WINDOW(sample_rate) (4 * LOUDNESS_STEP(sample_rate)) /* 400 ms */ #define OFFSET(x) offsetof(SilenceDetectContext, x) #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_AUDIO_PARAM static const AVOption silencedetect_options[] = { + { "mode", "set how to detect silence", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=MODE_PEAK}, 0, MODE_NB-1,FLAGS, .unit = "mode" }, + { "peak", "detect each sample peak", 0, AV_OPT_TYPE_CONST, {.i64=MODE_PEAK}, 0, 0, FLAGS, .unit = "mode" }, + { "loudness", "detect momentary loudness", 0, AV_OPT_TYPE_CONST, {.i64=MODE_LOUDNESS}, 0, 0, FLAGS, .unit = "mode" }, { "n", "set noise tolerance", OFFSET(noise), AV_OPT_TYPE_DOUBLE, {.dbl=0.001}, 0, DBL_MAX, FLAGS }, { "noise", "set noise tolerance", OFFSET(noise), AV_OPT_TYPE_DOUBLE, {.dbl=0.001}, 0, DBL_MAX, FLAGS }, { "d", "set minimum duration in seconds", OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64=2000000}, 0, MAX_DURATION,FLAGS }, @@ -100,6 +118,14 @@ static av_always_inline void update(AVFilterContext *ctx, AVFrame *insamples, int64_t end_pts = insamples ? insamples->pts + av_rescale_q(current_sample / s->channels, (AVRational){ 1, s->last_sample_rate }, time_base) : s->frame_end; + + /* momentary loudness lags the actual signal by up to the window + * size when it rises, so report the end of silence earlier to + * compensate, except at the end of the stream */ + if (insamples && s->mode == MODE_LOUDNESS) + end_pts -= av_rescale_q(LOUDNESS_WINDOW(s->last_sample_rate), + (AVRational){ 1, s->last_sample_rate }, time_base); + int64_t duration_ts = end_pts - s->start[channel]; if (insamples) { set_meta(insamples, s->mono ? channel + 1 : 0, "silence_end", @@ -163,6 +189,70 @@ SILENCE_DETECT_PLANAR(fltp, float) SILENCE_DETECT_PLANAR(s32p, int32_t) SILENCE_DETECT_PLANAR(s16p, int16_t) +static void update_loudness(SilenceDetectContext *s) +{ + /* measure the loudness every 100ms, per ITU-R BS.1770 */ + if (--s->nb_pending_samples) + return; + + s->nb_pending_samples = LOUDNESS_STEP(s->last_sample_rate); + for (int ch = 0; ch < s->channels; ch++) { + double loudness; + ff_ebur128_loudness_momentary(s->r128[ch], &loudness); + s->is_silence[ch] = loudness < s->noise; + } +} + +#define SILENCE_DETECT_LOUDNESS(name, type) \ +static void silencedetect_##name(AVFilterContext *ctx, AVFrame *insamples, \ + int nb_samples, int64_t nb_samples_notify, \ + AVRational time_base) \ +{ \ + SilenceDetectContext *s = ctx->priv; \ + const int channels = insamples->ch_layout.nb_channels; \ + const type *p = (const type *) insamples->data[0]; \ + \ + nb_samples /= channels; \ + for (int i = 0; i < nb_samples; i++) { \ + for (int ch = 0; ch < channels; ch++, p++) { \ + update(ctx, insamples, s->is_silence[ch], channels * i + ch, \ + nb_samples_notify, time_base); \ + ff_ebur128_add_frames_##type(s->r128[ch], p, 1); \ + } \ + update_loudness(s); \ + } \ +} + +#define SILENCE_DETECT_LOUDNESS_PLANAR(name, type) \ +static void silencedetect_##name(AVFilterContext *ctx, AVFrame *insamples, \ + int nb_samples, int64_t nb_samples_notify, \ + AVRational time_base) \ +{ \ + SilenceDetectContext *s = ctx->priv; \ + const int channels = insamples->ch_layout.nb_channels; \ + \ + nb_samples /= channels; \ + for (int i = 0; i < nb_samples; i++) { \ + for (int ch = 0; ch < channels; ch++) { \ + const type *p = (const type *) insamples->extended_data[ch]; \ + update(ctx, insamples, s->is_silence[ch], channels * i + ch, \ + nb_samples_notify, time_base); \ + ff_ebur128_add_frames_##type(s->r128[ch], &p[i], 1); \ + } \ + update_loudness(s); \ + } \ +} + +SILENCE_DETECT_LOUDNESS(dbl_loudness, double) +SILENCE_DETECT_LOUDNESS(flt_loudness, float) +SILENCE_DETECT_LOUDNESS(s32_loudness, int) +SILENCE_DETECT_LOUDNESS(s16_loudness, short) + +SILENCE_DETECT_LOUDNESS_PLANAR(dblp_loudness, double) +SILENCE_DETECT_LOUDNESS_PLANAR(fltp_loudness, float) +SILENCE_DETECT_LOUDNESS_PLANAR(s32p_loudness, int) +SILENCE_DETECT_LOUDNESS_PLANAR(s16p_loudness, short) + static int config_input(AVFilterLink *inlink) { AVFilterContext *ctx = inlink->dst; @@ -182,29 +272,61 @@ static int config_input(AVFilterLink *inlink) for (c = 0; c < s->independent_channels; c++) s->start[c] = INT64_MIN; - switch (inlink->format) { - case AV_SAMPLE_FMT_DBL: s->silencedetect = silencedetect_dbl; break; - case AV_SAMPLE_FMT_FLT: s->silencedetect = silencedetect_flt; break; - case AV_SAMPLE_FMT_S32: - s->noise *= INT32_MAX; - s->silencedetect = silencedetect_s32; + switch (s->mode) { + case MODE_PEAK: + switch (inlink->format) { + case AV_SAMPLE_FMT_DBL: s->silencedetect = silencedetect_dbl; break; + case AV_SAMPLE_FMT_FLT: s->silencedetect = silencedetect_flt; break; + case AV_SAMPLE_FMT_S32: + s->noise *= INT32_MAX; + s->silencedetect = silencedetect_s32; + break; + case AV_SAMPLE_FMT_S16: + s->noise *= INT16_MAX; + s->silencedetect = silencedetect_s16; + break; + case AV_SAMPLE_FMT_DBLP: s->silencedetect = silencedetect_dblp; break; + case AV_SAMPLE_FMT_FLTP: s->silencedetect = silencedetect_fltp; break; + case AV_SAMPLE_FMT_S32P: + s->noise *= INT32_MAX; + s->silencedetect = silencedetect_s32p; + break; + case AV_SAMPLE_FMT_S16P: + s->noise *= INT16_MAX; + s->silencedetect = silencedetect_s16p; + break; + default: + return AVERROR_BUG; + } break; - case AV_SAMPLE_FMT_S16: - s->noise *= INT16_MAX; - s->silencedetect = silencedetect_s16; + + case MODE_LOUDNESS: + s->r128 = av_calloc(s->channels, sizeof(*s->r128)); + s->is_silence = av_calloc(s->channels, sizeof(*s->is_silence)); + if (!s->r128 || !s->is_silence) + return AVERROR(ENOMEM); + for (c = 0; c < s->channels; c++) { + s->r128[c] = ff_ebur128_init(1, inlink->sample_rate, 0, FF_EBUR128_MODE_M); + if (!s->r128[c]) + return AVERROR(ENOMEM); + } + s->nb_pending_samples = LOUDNESS_STEP(inlink->sample_rate); + s->noise = 20 * log10(s->noise); /* convert to LUFS */ + /* silence must outlast the window its end is moved back by, see update() */ + s->duration += LOUDNESS_WINDOW(inlink->sample_rate); + + switch (inlink->format) { + case AV_SAMPLE_FMT_DBL: s->silencedetect = silencedetect_dbl_loudness; break; + case AV_SAMPLE_FMT_FLT: s->silencedetect = silencedetect_flt_loudness; break; + case AV_SAMPLE_FMT_S32: s->silencedetect = silencedetect_s32_loudness; break; + case AV_SAMPLE_FMT_S16: s->silencedetect = silencedetect_s16_loudness; break; + case AV_SAMPLE_FMT_DBLP: s->silencedetect = silencedetect_dblp_loudness; break; + case AV_SAMPLE_FMT_FLTP: s->silencedetect = silencedetect_fltp_loudness; break; + case AV_SAMPLE_FMT_S32P: s->silencedetect = silencedetect_s32p_loudness; break; + case AV_SAMPLE_FMT_S16P: s->silencedetect = silencedetect_s16p_loudness; break; + default: return AVERROR_BUG; + } break; - case AV_SAMPLE_FMT_DBLP: s->silencedetect = silencedetect_dblp; break; - case AV_SAMPLE_FMT_FLTP: s->silencedetect = silencedetect_fltp; break; - case AV_SAMPLE_FMT_S32P: - s->noise *= INT32_MAX; - s->silencedetect = silencedetect_s32p; - break; - case AV_SAMPLE_FMT_S16P: - s->noise *= INT16_MAX; - s->silencedetect = silencedetect_s16p; - break; - default: - return AVERROR_BUG; } return 0; @@ -221,10 +343,11 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) int c; // scale number of null samples to the new sample rate - if (s->last_sample_rate && s->last_sample_rate != srate) - for (c = 0; c < s->independent_channels; c++) { + if (s->last_sample_rate && s->last_sample_rate != srate) { + for (c = 0; c < s->independent_channels; c++) s->nb_null_samples[c] = srate * s->nb_null_samples[c] / s->last_sample_rate; - } + s->nb_pending_samples = srate * s->nb_pending_samples / s->last_sample_rate; + } s->last_sample_rate = srate; s->time_base = inlink->time_base; s->frame_end = insamples->pts + av_rescale_q(insamples->nb_samples, @@ -244,6 +367,10 @@ static av_cold void uninit(AVFilterContext *ctx) for (c = 0; c < s->independent_channels; c++) if (s->start[c] > INT64_MIN) update(ctx, NULL, 0, c, 0, s->time_base); + for (c = 0; s->r128 && c < s->channels; c++) + ff_ebur128_destroy(&s->r128[c]); + av_freep(&s->r128); + av_freep(&s->is_silence); av_freep(&s->nb_null_samples); av_freep(&s->start); } -- 2.52.0 >From 4e4aa0436088325b1fe3c00379ce7fa10919c884 Mon Sep 17 00:00:00 2001 From: Niklas Haas <[email protected]> Date: Mon, 14 Sep 2026 17:31:50 +0200 Subject: [PATCH 4/4] tests/fate/filter-video: add af_silencedetect loudness mode test Signed-off-by: Niklas Haas <[email protected]> --- tests/fate/filter-video.mak | 4 ++++ .../ref/fate/filter-metadata-silencedetect-loudness | 12 ++++++++++++ 2 files changed, 16 insertions(+) create mode 100644 tests/ref/fate/filter-metadata-silencedetect-loudness diff --git a/tests/fate/filter-video.mak b/tests/fate/filter-video.mak index ebbc0a7d1c..8551212890 100644 --- a/tests/fate/filter-video.mak +++ b/tests/fate/filter-video.mak @@ -918,6 +918,10 @@ FATE_METADATA_FILTER-$(call ALLYES, $(SILENCEDETECT_DEPS)) += fate-filter-metada fate-filter-metadata-silencedetect: SRC = $(TARGET_SAMPLES)/lossless-audio/inside.tta fate-filter-metadata-silencedetect: CMD = run $(FILTER_METADATA_COMMAND) "amovie='$(SRC)',silencedetect=n=-33.5dB:d=0.2" +FATE_METADATA_FILTER-$(call ALLYES, $(SILENCEDETECT_DEPS)) += fate-filter-metadata-silencedetect-loudness +fate-filter-metadata-silencedetect-loudness: SRC = $(TARGET_SAMPLES)/lossless-audio/inside.tta +fate-filter-metadata-silencedetect-loudness: CMD = run $(FILTER_METADATA_COMMAND) "amovie='$(SRC)',silencedetect=mode=loudness:n=-30dB:d=0.3" + EBUR128_METADATA_DEPS = LAVFI_INDEV AMOVIE_FILTER FLAC_DEMUXER FLAC_DECODER ARESAMPLE_FILTER EBUR128_FILTER FATE_METADATA_FILTER-$(call ALLYES, $(EBUR128_METADATA_DEPS)) += fate-filter-metadata-ebur128 fate-filter-metadata-ebur128: SRC = $(TARGET_SAMPLES)/filter/seq-3341-7_seq-3342-5-24bit.flac diff --git a/tests/ref/fate/filter-metadata-silencedetect-loudness b/tests/ref/fate/filter-metadata-silencedetect-loudness new file mode 100644 index 0000000000..11b35037eb --- /dev/null +++ b/tests/ref/fate/filter-metadata-silencedetect-loudness @@ -0,0 +1,12 @@ +pts=0|tag:lavfi.silence_start=0.1 +pts=46080|tag:lavfi.silence_end=1.5|tag:lavfi.silence_duration=1.4 +pts=92160 +pts=138240 +pts=184320 +pts=230400 +pts=276480 +pts=322560 +pts=368640 +pts=414720 +pts=460800 +pts=506880 -- 2.52.0 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
