diff --git a/transcode.c b/transcode.c
index 928d6316ae3b0a8b29e9d01eec0ec228ad8877a0..782e9a4cfb161dab9103fcc6c08f40b8e19b4f7b 100644
--- a/transcode.c
+++ b/transcode.c
@@ -223,6 +223,25 @@ static void filtergraph_send(AVFilterContext *src, AVCodecContext *dec, AVPacket
 	av_frame_free(&frame);
 }
 
+void connect_pads(AVFilterInOut **ins, AVFilterInOut **outs)
+{
+	int err;
+	AVFilterInOut *in, *out;
+	/* TODO: Really remove matched pads from ins/outs */
+	for (in = *ins; in; in = in->next)
+	{
+		if (!in->name)
+			continue;
+		for (out = *outs; out && (!out->name || strcmp(in->name, out->name));
+				out = out->next);
+		if (!out)
+			continue;
+		if ((err = avfilter_link(in->filter_ctx, in->pad_idx, out->filter_ctx, out->pad_idx)) < 0)
+			job_failed("Could not connect remaining filter pads named \"%s\": %s", in->name, av_err2str(err));
+		out->name = 0;
+	}
+}
+
 int main(int argc, char *argv[])
 {
 	int err, i, progress, _progress;
@@ -280,10 +299,10 @@ int main(int argc, char *argv[])
 	for (i = 0, p = jenter(jlookup(output, "streams")); p; i ++, p = jnext(p))
 		prepare_output_stream(p, avformat_new_stream(mux, 0), encs, fg, sinks, &outpads);
 
-	/* TODO: Connect pads of same name before applying any filter strings */
 	for (p = jenter(jlookup(argv[4], "filters")); p; p = jnext(p))
 		if ((err = avfilter_graph_parse_ptr(fg, jstr(p, "ERROR"), &outpads, &inpads, 0)) < 0)
 			job_failed("Parsing filter string \"%s\" failed: %s", jstr(p, 0), av_err2str(err));
+	connect_pads(&inpads, &outpads);
 	if (avfilter_graph_config(fg, 0) < 0)
 		job_failed("Error configuring filter graph: %s", av_err2str(err));