MusicPlayerDaemon / MPD

Music Player Daemon
https://www.musicpd.org/
GNU General Public License v2.0
2.19k stars 350 forks source link

Possibility of including cover art in icecast2 stream #626

Open JustArchi opened 5 years ago

JustArchi commented 5 years ago

Feature request

Right now MPD server doesn't deal with binary metadata of the audio file, especially cover arts. It's also impossible to add it through metadata_to_use, as non-defined tags like +METADATA_BLOCK_PICTURE cause MPD failing to start with exception: error parsing metadata item "METADATA_BLOCK_PICTURE" message. Adding it as an option to metadata_to_use would probably work, but would also put unnecessary overhead due to caching as part of tag_cache and being available for queries, which is suboptimal considering it's binary and doesn't need to be cached in advance, just as audio stream.

I'd like to request a way for MPD to treat certain metadata blocks as binary, such as adding binary_metadata_to_use property. That is, they wouldn't be normally cached in tag_cache (as they're not readable text), but rather be read as part of the file (same as audio stream currently) and sent to the listener as usual by being appended to appropriate metadata tags, such as OpusTags for opus codec. This way, I could use binary_metadata_to_use "+METADATA_BLOCK_PICTURE" in order to tell MPD to extract METADATA_BLOCK_PICTURE (if available) as part of the file read, and broadcast it with the rest of the tags.

There are also other use cases that would benefit from the above, mainly tags that we'd like to send, but not necessarily read in advance and cache. Examples might include stuff like encoded lyrics, band logotype (part of ID3v2), METADATA_BLOCK_CUESHEET and other metadata that we might potentially want to transmit, but we don't need to cache and read in advance.

I found similar issue #42, but based on reading it, it covers MPD clients and not MPD server. I don't need mpc to return me the art, I need MPD to send the tag as part of the currently played file to the icecast2 stream.

As usual I'm attaching a sample file to make testing a bit easier. The end goal is to connect to icecast2 mpd stream (I use opus encoder with opustags "true") and see the cover art in program like VLC.

sample.zip

Thank you in advance for considering this feature request. As usual the above is only my suggestion as to what can be done, I'll be happy with any solution that would allow me to embed METADATA_BLOCK_PICTURE in my opus icecast2 stream, read directly from the files.

MaxKellermann commented 5 years ago

How do you want MPD to send those embedded picture files to Icecast?

JustArchi commented 5 years ago

That depends upon the codec, for opus files we have OpusTags that could include the block. Vorbis in OGG container also has a field for that, and there is ID3v2 for the rest.

I'm not entirely sure in the actual technical implementation (and whether you can use OpusTags for icecast2 stream), but I've verified that at least mopidy (another app like mpd) is able to send those through icecast2 stream and they show correctly in the VLC, both for stream start and song changes (and it's not the VLC client searching based on metadata from the internet). I'm not exactly sure how they achieved that. Mopidy has a lot of other issues though, and I'd love to use MPD with this feature.

JustArchi commented 5 years ago

Looking in MPD's source code, I see SendTag which I'm pretty sure that would work fine if you just transmitted METADATA_BLOCK_PICTURE to it, as it's just base64-encoded string that the client is expected to decode itself. I don't see how that tag would be different from all other ones that are already transmitted. It's simply not read and not parsed currently in MPD, so also not transmitted.

Of course I realize that if encoder doesn't ImplementsTag() then the only way is fallback to icecast metadata, in which case I'm not sure if you're allowed to set arbitrary metadata key-value pairs, but even if you can't do that apart from some predefined metadata blocks, it's completely fine as I never expected this fallback to work with my use case, I expect this to work with OpusTags when enabling opustags "true" chaining.

Therefore, if that makes a bit more sense, if icecast2 metadata doesn't accept arbitrary key-values to set, it's totally fine to have this behaviour enabled only for encoders that ImplementsTag(). I hope that this helps, thank you.

And of course, making it possible would likely also benefit httpd audio output and perhaps some other ones that also use streaming.