diff --git a/Makefile.am b/Makefile.am
index 0041320b9..51991920e 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1198,6 +1198,7 @@ ENCODER_LIBS = \
 	$(VORBISENC_LIBS)
 
 libencoder_plugins_a_SOURCES = \
+	src/encoder/Configured.cxx src/encoder/Configured.hxx \
 	src/encoder/EncoderAPI.hxx \
 	src/encoder/EncoderInterface.hxx \
 	src/encoder/EncoderPlugin.hxx \
diff --git a/src/encoder/Configured.cxx b/src/encoder/Configured.cxx
new file mode 100644
index 000000000..4e6c900f8
--- /dev/null
+++ b/src/encoder/Configured.cxx
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2003-2017 The Music Player Daemon Project
+ * http://www.musicpd.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+#include "Configured.hxx"
+#include "EncoderList.hxx"
+#include "EncoderPlugin.hxx"
+#include "config/Block.hxx"
+#include "util/StringAPI.hxx"
+#include "util/RuntimeError.hxx"
+
+static const EncoderPlugin &
+GetConfiguredEncoderPlugin(const ConfigBlock &block, bool shout_legacy)
+{
+	const char *name = block.GetBlockValue("encoder", nullptr);
+	if (name == nullptr && shout_legacy)
+		name = block.GetBlockValue("encoding", nullptr);
+
+	if (name == nullptr)
+		name = "vorbis";
+
+	if (shout_legacy) {
+		if (StringIsEqual(name, "ogg"))
+			name = "vorbis";
+		else if (StringIsEqual(name, "mp3"))
+			name = "lame";
+	}
+
+	const auto plugin = encoder_plugin_get(name);
+	if (plugin == nullptr)
+		throw FormatRuntimeError("No such encoder: %s", name);
+
+	return *plugin;
+}
+
+PreparedEncoder *
+CreateConfiguredEncoder(const ConfigBlock &block, bool shout_legacy)
+{
+	return encoder_init(GetConfiguredEncoderPlugin(block, shout_legacy),
+			    block);
+}
diff --git a/src/encoder/Configured.hxx b/src/encoder/Configured.hxx
new file mode 100644
index 000000000..b2ebd2d7d
--- /dev/null
+++ b/src/encoder/Configured.hxx
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2003-2017 The Music Player Daemon Project
+ * http://www.musicpd.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef MPD_ENCODER_CONFIGURED_HXX
+#define MPD_ENCODER_CONFIGURED_HXX
+
+struct ConfigBlock;
+class PreparedEncoder;
+
+/**
+ * Create a #PreparedEncoder instance from the settings in the
+ * #ConfigBlock.  Its "encoder" setting is used to choose the encoder
+ * plugin.
+ *
+ * Throws an exception on error.
+ *
+ * @param shout_legacy enable the "shout" plugin legacy configuration?
+ * i.e. fall back to setting "encoding" instead of "encoder"
+ */
+PreparedEncoder *
+CreateConfiguredEncoder(const ConfigBlock &block, bool shout_legacy=false);
+
+#endif
diff --git a/src/output/plugins/RecorderOutputPlugin.cxx b/src/output/plugins/RecorderOutputPlugin.cxx
index 1e561fb39..4d39df9e2 100644
--- a/src/output/plugins/RecorderOutputPlugin.cxx
+++ b/src/output/plugins/RecorderOutputPlugin.cxx
@@ -23,14 +23,12 @@
 #include "tag/Format.hxx"
 #include "encoder/ToOutputStream.hxx"
 #include "encoder/EncoderInterface.hxx"
-#include "encoder/EncoderPlugin.hxx"
-#include "encoder/EncoderList.hxx"
+#include "encoder/Configured.hxx"
 #include "config/ConfigError.hxx"
 #include "config/ConfigPath.hxx"
 #include "Log.hxx"
 #include "fs/AllocatedPath.hxx"
 #include "fs/io/FileOutputStream.hxx"
-#include "util/RuntimeError.hxx"
 #include "util/Domain.hxx"
 #include "util/ScopeExit.hxx"
 
@@ -109,16 +107,11 @@ private:
 };
 
 RecorderOutput::RecorderOutput(const ConfigBlock &block)
-	:AudioOutput(0)
+	:AudioOutput(0),
+	 prepared_encoder(CreateConfiguredEncoder(block))
 {
 	/* read configuration */
 
-	const char *encoder_name =
-		block.GetBlockValue("encoder", "vorbis");
-	const auto encoder_plugin = encoder_plugin_get(encoder_name);
-	if (encoder_plugin == nullptr)
-		throw FormatRuntimeError("No such encoder: %s", encoder_name);
-
 	path = block.GetPath("path");
 
 	const char *fmt = block.GetBlockValue("format_path", nullptr);
@@ -130,10 +123,6 @@ RecorderOutput::RecorderOutput(const ConfigBlock &block)
 
 	if (!path.IsNull() && fmt != nullptr)
 		throw std::runtime_error("Cannot have both 'path' and 'format_path'");
-
-	/* initialize encoder */
-
-	prepared_encoder.reset(encoder_init(*encoder_plugin, block));
 }
 
 inline void
diff --git a/src/output/plugins/ShoutOutputPlugin.cxx b/src/output/plugins/ShoutOutputPlugin.cxx
index b30dae91d..6485e4140 100644
--- a/src/output/plugins/ShoutOutputPlugin.cxx
+++ b/src/output/plugins/ShoutOutputPlugin.cxx
@@ -21,8 +21,7 @@
 #include "ShoutOutputPlugin.hxx"
 #include "../OutputAPI.hxx"
 #include "encoder/EncoderInterface.hxx"
-#include "encoder/EncoderPlugin.hxx"
-#include "encoder/EncoderList.hxx"
+#include "encoder/Configured.hxx"
 #include "util/RuntimeError.hxx"
 #include "util/Domain.hxx"
 #include "util/StringAPI.hxx"
@@ -88,17 +87,6 @@ require_block_string(const ConfigBlock &block, const char *name)
 	return value;
 }
 
-static const EncoderPlugin *
-shout_encoder_plugin_get(const char *name)
-{
-	if (strcmp(name, "ogg") == 0)
-		name = "vorbis";
-	else if (strcmp(name, "mp3") == 0)
-		name = "lame";
-
-	return encoder_plugin_get(name);
-}
-
 static void
 ShoutSetAudioInfo(shout_t *shout_conn, const AudioFormat &audio_format)
 {
@@ -114,7 +102,8 @@ ShoutSetAudioInfo(shout_t *shout_conn, const AudioFormat &audio_format)
 ShoutOutput::ShoutOutput(const ConfigBlock &block)
 	:AudioOutput(FLAG_PAUSE),
 	 shout_conn(shout_new()),
-	 shout_meta(shout_metadata_new())
+	 shout_meta(shout_metadata_new()),
+	 prepared_encoder(CreateConfiguredEncoder(block, true))
 {
 	NeedFullyDefinedAudioFormat();
 
@@ -156,16 +145,6 @@ ShoutOutput::ShoutOutput(const ConfigBlock &block)
 			throw std::runtime_error("bitrate must be a positive integer");
 	}
 
-	const char *encoding = block.GetBlockValue("encoder", nullptr);
-	if (encoding == nullptr)
-		encoding = block.GetBlockValue("encoding", "vorbis");
-	const auto encoder_plugin = shout_encoder_plugin_get(encoding);
-	if (encoder_plugin == nullptr)
-		throw FormatRuntimeError("couldn't find shout encoder plugin \"%s\"",
-					 encoding);
-
-	prepared_encoder.reset(encoder_init(*encoder_plugin, block));
-
 	const char *const mime_type = prepared_encoder->GetMimeType();
 
 	unsigned shout_format;
diff --git a/src/output/plugins/httpd/HttpdOutputPlugin.cxx b/src/output/plugins/httpd/HttpdOutputPlugin.cxx
index 49a7c8f5b..731a5053a 100644
--- a/src/output/plugins/httpd/HttpdOutputPlugin.cxx
+++ b/src/output/plugins/httpd/HttpdOutputPlugin.cxx
@@ -23,15 +23,13 @@
 #include "HttpdClient.hxx"
 #include "output/OutputAPI.hxx"
 #include "encoder/EncoderInterface.hxx"
-#include "encoder/EncoderPlugin.hxx"
-#include "encoder/EncoderList.hxx"
+#include "encoder/Configured.hxx"
 #include "net/UniqueSocketDescriptor.hxx"
 #include "net/SocketAddress.hxx"
 #include "net/ToString.hxx"
 #include "Page.hxx"
 #include "IcyMetaDataServer.hxx"
 #include "event/Call.hxx"
-#include "util/RuntimeError.hxx"
 #include "util/Domain.hxx"
 #include "util/DeleteDisposer.hxx"
 #include "Log.hxx"
@@ -52,6 +50,7 @@ inline
 HttpdOutput::HttpdOutput(EventLoop &_loop, const ConfigBlock &block)
 	:AudioOutput(FLAG_ENABLE_DISABLE|FLAG_PAUSE),
 	 ServerSocket(_loop),
+	 prepared_encoder(CreateConfiguredEncoder(block)),
 	 defer_broadcast(_loop, BIND_THIS_METHOD(OnDeferredBroadcast))
 {
 	/* read configuration */
@@ -61,12 +60,6 @@ HttpdOutput::HttpdOutput(EventLoop &_loop, const ConfigBlock &block)
 
 	unsigned port = block.GetBlockValue("port", 8000u);
 
-	const char *encoder_name =
-		block.GetBlockValue("encoder", "vorbis");
-	const auto encoder_plugin = encoder_plugin_get(encoder_name);
-	if (encoder_plugin == nullptr)
-		throw FormatRuntimeError("No such encoder: %s", encoder_name);
-
 	clients_max = block.GetBlockValue("max_clients", 0u);
 
 	/* set up bind_to_address */
@@ -77,10 +70,6 @@ HttpdOutput::HttpdOutput(EventLoop &_loop, const ConfigBlock &block)
 	else
 		AddPort(port);
 
-	/* initialize encoder */
-
-	prepared_encoder.reset(encoder_init(*encoder_plugin, block));
-
 	/* determine content type */
 	content_type = prepared_encoder->GetMimeType();
 	if (content_type == nullptr)