diff --git a/NEWS b/NEWS
index b0f393f57..1c0df1aa7 100644
--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,7 @@
 ver 0.22.7 (not yet released)
 * protocol
   - don't use glibc extension to parse time stamps
+  - optimize the "albumart" command
 * input
   - curl: send user/password in the first request, save one roundtrip
 * decoder
diff --git a/src/client/Client.hxx b/src/client/Client.hxx
index deb4b8caa..3e0e2fdec 100644
--- a/src/client/Client.hxx
+++ b/src/client/Client.hxx
@@ -23,6 +23,7 @@
 #include "Message.hxx"
 #include "command/CommandResult.hxx"
 #include "command/CommandListBuilder.hxx"
+#include "input/LastInputStream.hxx"
 #include "tag/Mask.hxx"
 #include "event/FullyBufferedSocket.hxx"
 #include "event/TimerEvent.hxx"
@@ -90,6 +91,13 @@ public:
 	 */
 	size_t binary_limit = 8192;
 
+	/**
+	 * This caches the last "albumart" InputStream instance, to
+	 * avoid repeating the search for each chunk requested by this
+	 * client.
+	 */
+	LastInputStream last_album_art;
+
 private:
 	static constexpr size_t MAX_SUBSCRIPTIONS = 16;
 
diff --git a/src/client/New.cxx b/src/client/New.cxx
index 75019290f..f9633816c 100644
--- a/src/client/New.cxx
+++ b/src/client/New.cxx
@@ -44,7 +44,8 @@ Client::Client(EventLoop &_loop, Partition &_partition,
 	 partition(&_partition),
 	 permission(_permission),
 	 uid(_uid),
-	 num(_num)
+	 num(_num),
+	 last_album_art(_loop)
 {
 	timeout_event.Schedule(client_timeout);
 }
diff --git a/src/command/FileCommands.cxx b/src/command/FileCommands.cxx
index 7efbb211c..739cc6579 100644
--- a/src/command/FileCommands.cxx
+++ b/src/command/FileCommands.cxx
@@ -191,9 +191,16 @@ read_stream_art(Response &r, const char *uri, size_t offset)
 {
 	const auto art_directory = PathTraitsUTF8::GetParent(uri);
 
-	Mutex mutex;
+	// TODO: eliminate this const_cast
+	auto &client = const_cast<Client &>(r.GetClient());
 
-	InputStreamPtr is = find_stream_art(art_directory, mutex);
+	/* to avoid repeating the search for each chunk request by the
+	   same client, use the #LastInputStream class to cache the
+	   #InputStream instance */
+	auto *is = client.last_album_art.Open(art_directory, [](std::string_view directory,
+								Mutex &mutex){
+		return find_stream_art(directory, mutex);
+	});
 
 	if (is == nullptr) {
 		r.Error(ACK_ERROR_NO_EXIST, "No file exists");
@@ -219,7 +226,7 @@ read_stream_art(Response &r, const char *uri, size_t offset)
 
 	std::size_t read_size = 0;
 	if (buffer_size > 0) {
-		std::unique_lock<Mutex> lock(mutex);
+		std::unique_lock<Mutex> lock(is->mutex);
 		is->Seek(lock, offset);
 		read_size = is->Read(lock, buffer.get(), buffer_size);
 	}