godotengine / godot-proposals

Godot Improvement Proposals (GIPs)
MIT License
1.11k stars 69 forks source link

Decode and expose Ogg Vorbis/MP3/WAV comment metadata tags #3307

Open TBleader opened 2 years ago

TBleader commented 2 years ago

Describe the project you are working on

A 4x space game. Overly ambitious, likely never going to go anywhere. But it's fun to dream!

Describe the problem or limitation you are having in your project

For the music player I am currently defining the music meta data using an extra file that contains the song title, album, and artist. This data is encoded in the ogg files directly however, but it is inaccessible.

Describe the feature / enhancement and how it helps to overcome the problem or limitation

Adding the Title, Artist, Album, Date, other common music meta data to the audio container would eliminate the need for extra data definitions for this information provided the audio has that defined. It is commonly defined for music for example. This would simplify displaying/collecting this information.

(Sometimes cover art is contained in a Vorbis Comment and it would certainly be cool if a Texture was created from that, but I feel it would be a much less used than the other meta data information.)

Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams

When the audio is imported the header containing the vorbis comment can get decoded and if there is any metadata it can be added to the AudioStreamOGGVorbis. Perhaps it could be accessed directly such as with AudioStreamOGGVorbis.Title or it could be contained in some kind of data object that might contain it but could be checked such as AudioStreamOGGVorbis.HeaderData.Title

I am not overly familiar with WAV but it seems like it can contain meta data as well so perhaps this proposal could be more generalized to supporting meta data from both, but I initially have focused on Ogg Vorbis.

MP3 commonly has metadata as well, but I have not tried to use MP3 with Godot. Ogg was suggested in the documentation. But if support was extended to the other file types then the meta data container could be instead added to AudioStream and then inherited by AudioStreamOGGVorbis, AudioStreamSample, and AudioStreamMP3 so that any format could be checked for meta data.

If this enhancement will not be used often, can it be worked around with a few lines of script?

Presently with C# using a library and loading the streams data property it could be extracted. I was also advised that this will not be possible in 4.0 due to some changes, but there might be another work around involving extracting the packed ogg page data. I was informed that the header pages are already being kept so it might be possible.

It might be possible to work around it in GDScript by binding a library in GDNative or C#, but I am not overly familiar with GDScript to know how feasible or workable that would be.

It would certainly be nice to have the engine just retain this meta data instead of having to maintain separate data files to define the information.

Is there a reason why this should be core and not an add-on in the asset library?

The core engine handles importing and playing of Audio, it seems like it would not make sense for this feature to be an add-on specifically. An add-on could be made to 'simplify' the workaround process, but I feel instead it should just be handled by the engine.

I was informed that this is probably a reasonable change, but there is a lot on the to-do list already and it might not happen "in the near future" which is perfectly reasonable. I figured it wouldn't hurt to make a formal proposal though for keeping track. As far as I could tell one does not exist for this, but if it does then this could be closed.

Calinou commented 2 years ago

I'm OK with exposing this information, as long as the implementation doesn't require too much additional code compared to what we have now. The main use case I can think of is providing attribution information for soundtrack when a new track is played:

image

This is not legally required most of the time, but it's a nice option to provide when your game features music from different artists. It's not limited to AAA games either – I remember seeing many indie games such as N++ feature similar boxes when a new music track starts.

Note that in the master branch, libvorbis is now used instead of stb_vorbis. Therefore, this is likely easier to implement in master compared to 3.x.

Also, we should look at supporting loop points from Ogg Vorbis files eventually.

Catastrphic commented 1 year ago

is this going to be (or already is) in godot 4? it's very useful.

Calinou commented 1 year ago

is this going to be (or already is) in godot 4? it's very useful.

To my knowledge, nobody has started working on this. As a result, there's no ETA for having this implemented.

ChaunceyHoover commented 1 month ago

This is probably something WAY over my skill level, but I'd love to at least try to take a stab at it. Could someone point me in the direction of either some documentation or maybe suggest a few areas of the engine I take a look at to see if it's something possible for me to accomplish? I apologize, I'm not very familiar with the layout of the repo just yet.

Calinou commented 1 month ago

@ChaunceyHoover The importers for various audio formats are here:

In terms of implementation, one way to achieve this would be to add a tags[^1] Dictionary property in AudioStreamWAV, AudioStreamOGGVorbis and AudioStreamMP3 with a format like this:

[^1]: I think the name tags is more appropriate, as metadata or meta could be confused with Object metadata, which is user-defined metadata available in every Godot object.

{
    "title": "Track Name",
    "artist": "Artist Name",
    "album": "Album Name",
    "year": 2024,
    ...
}

There can be a lot of metadata fields in a single audio file (and they can vary across audio formats), so I feel a dictionary is more appropriate than individual properties. I suggest keeping the keys close to the official standards, but it might be worth renaming some of them so that they match more closely across formats (e.g. you should be able to read artist on all audio formats, even if the official tag name for that property isn't artist).

Once this property is added, the various importers can fill in the AudioStream's tags property at import-time. Run-time Ogg Vorbis loading (ResourceImporterOggVorbis::load_from_file()) could also achieve this, which would enable the ability to read tags from user-provided audio files.