diff --git a/src/lib/ffmpeg/Filter.cxx b/src/lib/ffmpeg/Filter.cxx
index 51e43dc3d..d435ca5c8 100644
--- a/src/lib/ffmpeg/Filter.cxx
+++ b/src/lib/ffmpeg/Filter.cxx
@@ -100,6 +100,36 @@ MakeAudioBufferSink(AVFilterGraph &graph_ctx)
 			    graph_ctx);
 }
 
+AVFilterContext &
+MakeAformat(AudioFormat &audio_format,
+	    AVFilterGraph &graph_ctx)
+{
+	AVSampleFormat dest_format = ToFfmpegSampleFormat(audio_format.format);
+	if (dest_format == AV_SAMPLE_FMT_NONE) {
+		switch (audio_format.format) {
+		case SampleFormat::S24_P32:
+			audio_format.format = SampleFormat::S32;
+			dest_format = AV_SAMPLE_FMT_S32;
+			break;
+
+		default:
+			audio_format.format = SampleFormat::S16;
+			dest_format = AV_SAMPLE_FMT_S16;
+			break;
+		}
+	}
+
+	char args[256];
+	sprintf(args,
+		"sample_rates=%u:sample_fmts=%s:channel_layouts=0x%" PRIx64,
+		audio_format.sample_rate,
+		av_get_sample_fmt_name(dest_format),
+		ToFfmpegChannelLayout(audio_format.channels));
+
+	return CreateFilter(RequireFilterByName("aformat"), "aformat",
+			    args, nullptr, graph_ctx);
+}
+
 void
 FilterGraph::ParseSingleInOut(const char *filters, AVFilterContext &in,
 			      AVFilterContext &out)
diff --git a/src/lib/ffmpeg/Filter.hxx b/src/lib/ffmpeg/Filter.hxx
index f57af3c1b..c55ac2b1f 100644
--- a/src/lib/ffmpeg/Filter.hxx
+++ b/src/lib/ffmpeg/Filter.hxx
@@ -93,6 +93,16 @@ MakeAudioBufferSource(AudioFormat &audio_format,
 AVFilterContext &
 MakeAudioBufferSink(AVFilterGraph &graph_ctx);
 
+/**
+ * Create an "aformat" filter.
+ *
+ * @param the output audio format; may be modified by the function if
+ * the given format is not supported by libavfilter
+ */
+AVFilterContext &
+MakeAformat(AudioFormat &audio_format,
+	    AVFilterGraph &graph_ctx);
+
 class FilterGraph {
 	AVFilterGraph *graph = nullptr;