diff --git a/src/decoder_api.c b/src/decoder_api.c
index 93e4790c9..c777084c8 100644
--- a/src/decoder_api.c
+++ b/src/decoder_api.c
@@ -189,12 +189,18 @@ update_stream_tag(struct decoder *decoder, struct input_stream *is)
 {
 	struct tag *tag;
 
-	if (is == NULL)
-		return false;
+	tag = is != NULL
+		? input_stream_tag(is)
+		: NULL;
+	if (tag == NULL) {
+		tag = decoder->song_tag;
+		if (tag == NULL)
+			return false;
 
-	tag = input_stream_tag(is);
-	if (tag == NULL)
-		return false;
+		/* no stream tag present - submit the song tag
+		   instead */
+		decoder->song_tag = NULL;
+	}
 
 	if (decoder->stream_tag != NULL)
 		tag_free(decoder->stream_tag);
diff --git a/src/decoder_internal.h b/src/decoder_internal.h
index 566c49768..cf54dbf6d 100644
--- a/src/decoder_internal.h
+++ b/src/decoder_internal.h
@@ -30,6 +30,13 @@ struct decoder {
 
 	bool seeking;
 
+	/**
+	 * The tag from the song object.  This is only used for local
+	 * files, because we expect the stream server to send us a new
+	 * tag each time we play it.
+	 */
+	struct tag *song_tag;
+
 	/** the last tag received from the stream */
 	struct tag *stream_tag;
 
diff --git a/src/decoder_thread.c b/src/decoder_thread.c
index dee16218a..c649f3a34 100644
--- a/src/decoder_thread.c
+++ b/src/decoder_thread.c
@@ -95,6 +95,8 @@ static void decoder_run_song(const struct song *song, const char *uri)
 	}
 
 	decoder.seeking = false;
+	decoder.song_tag = song->tag != NULL && song_is_file(song)
+		? tag_dup(song->tag) : NULL;
 	decoder.stream_tag = NULL;
 	decoder.decoder_tag = NULL;
 	decoder.chunk = NULL;
@@ -201,6 +203,9 @@ static void decoder_run_song(const struct song *song, const char *uri)
 	if (close_instream)
 		input_stream_close(&input_stream);
 
+	if (decoder.song_tag != NULL)
+		tag_free(decoder.song_tag);
+
 	if (decoder.stream_tag != NULL)
 		tag_free(decoder.stream_tag);