diff --git a/libavfilter/avf_showspectrum.c b/libavfilter/avf_showspectrum.c
index a4dd7b7879..9425c4ded6 100644
--- a/libavfilter/avf_showspectrum.c
+++ b/libavfilter/avf_showspectrum.c
@@ -1606,91 +1606,90 @@ static const AVOption showspectrumpic_options[] = {
 
 AVFILTER_DEFINE_CLASS(showspectrumpic);
 
-static int showspectrumpic_request_frame(AVFilterLink *outlink)
+static int showspectrumpic_request_frame(AVFilterLink *outlink, int64_t samples)
 {
     AVFilterContext *ctx = outlink->src;
     ShowSpectrumContext *s = ctx->priv;
     AVFilterLink *inlink = ctx->inputs[0];
-    int ret, samples;
+    int consumed = 0;
+    int x = 0, sz = s->orientation == VERTICAL ? s->w : s->h;
+    int ret, ch, spf, spb;
+    AVFrame *fin = NULL;
 
-    ret = ff_request_frame(inlink);
-    samples = av_audio_fifo_size(s->fifo);
-    if (ret == AVERROR_EOF && s->outpicref && samples > 0) {
-        int consumed = 0;
-        int x = 0, sz = s->orientation == VERTICAL ? s->w : s->h;
-        int ch, spf, spb;
-        AVFrame *fin;
+    spf = s->win_size * (samples / ((s->win_size * sz) * ceil(samples / (float)(s->win_size * sz))));
+    spf = FFMAX(1, spf);
 
-        spf = s->win_size * (samples / ((s->win_size * sz) * ceil(samples / (float)(s->win_size * sz))));
-        spf = FFMAX(1, spf);
+    spb = (samples / (spf * sz)) * spf;
 
-        spb = (samples / (spf * sz)) * spf;
-
-        fin = ff_get_audio_buffer(inlink, s->win_size);
-        if (!fin)
-            return AVERROR(ENOMEM);
-
-        while (x < sz) {
-            ret = av_audio_fifo_peek(s->fifo, (void **)fin->extended_data, s->win_size);
-            if (ret < 0) {
-                av_frame_free(&fin);
-                return ret;
-            }
-
-            av_audio_fifo_drain(s->fifo, spf);
-
-            if (ret < s->win_size) {
-                for (ch = 0; ch < s->nb_display_channels; ch++) {
-                    memset(fin->extended_data[ch] + ret * sizeof(float), 0,
-                           (s->win_size - ret) * sizeof(float));
-                }
-            }
-
-            ctx->internal->execute(ctx, run_channel_fft, fin, NULL, s->nb_display_channels);
-            acalc_magnitudes(s);
-
-            consumed += spf;
-            if (consumed >= spb) {
-                int h = s->orientation == VERTICAL ? s->h : s->w;
+    while (x < sz) {
+        ret = ff_inlink_peek_samples(inlink, s->win_size, &fin);
+        if (ret < 0)
+            return ret;
+        if (ret == 0)
+            break;
 
-                scale_magnitudes(s, 1.f / (consumed / spf));
-                plot_spectrum_column(inlink, fin);
-                consumed = 0;
-                x++;
-                for (ch = 0; ch < s->nb_display_channels; ch++)
-                    memset(s->magnitudes[ch], 0, h * sizeof(float));
-            }
+        ctx->internal->execute(ctx, run_channel_fft, fin, NULL, s->nb_display_channels);
+        acalc_magnitudes(s);
+
+        consumed += spf;
+        if (consumed >= spb) {
+            int h = s->orientation == VERTICAL ? s->h : s->w;
+
+            scale_magnitudes(s, 1.f / (consumed / spf));
+            plot_spectrum_column(inlink, fin);
+            consumed = 0;
+            x++;
+            for (ch = 0; ch < s->nb_display_channels; ch++)
+                memset(s->magnitudes[ch], 0, h * sizeof(float));
         }
-
         av_frame_free(&fin);
-        s->outpicref->pts = 0;
+        ff_inlink_skip_samples(inlink, spf);
+    }
 
-        if (s->legend)
-            draw_legend(ctx, samples);
+    s->outpicref->pts = 0;
 
-        ret = ff_filter_frame(outlink, s->outpicref);
-        s->outpicref = NULL;
-    }
+    if (s->legend)
+        draw_legend(ctx, samples);
+
+    ret = ff_filter_frame(outlink, s->outpicref);
+    s->outpicref = NULL;
 
     return ret;
 }
 
-static int showspectrumpic_filter_frame(AVFilterLink *inlink, AVFrame *insamples)
+static int showspectrumpic_activate(AVFilterContext *ctx)
 {
-    AVFilterContext *ctx = inlink->dst;
+    AVFilterLink *inlink = ctx->inputs[0];
+    AVFilterLink *outlink = ctx->outputs[0];
     ShowSpectrumContext *s = ctx->priv;
     int ret;
 
-    ret = av_audio_fifo_write(s->fifo, (void **)insamples->extended_data, insamples->nb_samples);
-    av_frame_free(&insamples);
-    return ret;
+    FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink);
+
+    if (ff_outlink_get_status(inlink) == AVERROR_EOF &&
+        s->outpicref) {
+        int64_t samples = 0;
+
+        for (int i = 0; i < ff_inlink_queued_frames(inlink); i++) {
+            AVFrame *frame = ff_inlink_peek_frame(inlink, i);
+
+            samples += frame->nb_samples;
+        }
+
+        ret = showspectrumpic_request_frame(outlink, samples);
+        ff_outlink_set_status(outlink, AVERROR_EOF, 0);
+        return ret;
+    }
+
+    FF_FILTER_FORWARD_WANTED(outlink, inlink);
+
+    return FFERROR_NOT_READY;
 }
 
 static const AVFilterPad showspectrumpic_inputs[] = {
     {
         .name         = "default",
         .type         = AVMEDIA_TYPE_AUDIO,
-        .filter_frame = showspectrumpic_filter_frame,
     },
     { NULL }
 };
@@ -1700,7 +1699,6 @@ static const AVFilterPad showspectrumpic_outputs[] = {
         .name          = "default",
         .type          = AVMEDIA_TYPE_VIDEO,
         .config_props  = config_output,
-        .request_frame = showspectrumpic_request_frame,
     },
     { NULL }
 };
@@ -1711,6 +1709,7 @@ AVFilter ff_avf_showspectrumpic = {
     .uninit        = uninit,
     .query_formats = query_formats,
     .priv_size     = sizeof(ShowSpectrumContext),
+    .activate      = showspectrumpic_activate,
     .inputs        = showspectrumpic_inputs,
     .outputs       = showspectrumpic_outputs,
     .priv_class    = &showspectrumpic_class,
