androidx / media

Jetpack Media3 support libraries for media use cases, including ExoPlayer, an extensible media player for Android
https://developer.android.com/media/media3
Apache License 2.0
1.6k stars 377 forks source link

Add support for ID3 USLT unsynced lyrics tag #922

Open lyswhut opened 9 months ago

lyswhut commented 9 months ago

Hey, when I read the tag in the audio with MetadataRetriever, it works well in FLAC, but it cannot read the contents of the UNSYNCEDLYRICS tag in MP3, it is classified into BinaryFrame and cannot parse the data inside. Does it have no support for this?

The following is example code and sample file:

  private static class DirectExecutor implements Executor {
    public void execute(Runnable r) {
      r.run();
    }
  }
  public static void getMetadata(Context context, String uri) {
    ListenableFuture<TrackGroupArray> trackGroupsFuture = MetadataRetriever.retrieveMetadata(context, MediaItem.fromUri(uri));
    Futures.addCallback(trackGroupsFuture, new FutureCallback<>() {
      @Override
      public void onSuccess(TrackGroupArray trackGroups) {
        Log.d("Metadata", "trackGroups length: " + trackGroups.length);
        for (int i = 0; i < trackGroups.length; i++) {
          Log.d("Metadata", "index: " + i + " format length: " + trackGroups.get(i).length);
          Metadata metadata = trackGroups.get(i).getFormat(0).metadata;
          if (metadata == null) continue;
          Log.d("Metadata", "index: " + i + " metadata length: " + metadata.length());
          for(int i2 = 0; i2 < metadata.length(); i2++) {
            Metadata.Entry entry = metadata.get(i2);
            if ((entry instanceof ApicFrame pic)) {
              Log.d("Metadata", "id3 ApicFrame pictureType: " + pic.pictureType + " pictureData: " + pic.pictureData.length);
            } else if (entry instanceof TextInformationFrame id3) {
              Log.d("Metadata", "id3 TextInformationFrame key: " + id3.id.toUpperCase() + " value: " + id3.values.get(0));
            } else if (entry instanceof BinaryFrame binaryFrame) {
              Log.d("Metadata", "id3 BinaryFrame key: " + binaryFrame.id + " data: " + binaryFrame.data.length);
              if ("USLT".equalsIgnoreCase(binaryFrame.id)) Log.d("Metadata", "id3 UNSYNCEDLYRICS: " + new String(binaryFrame.data, StandardCharsets.UTF_8));
            }
          }
        }
      }
      @Override
      public void onFailure(@NonNull Throwable t) {
        Log.d("Metadata", "error: " + t);
      }
    }, new DirectExecutor());
  }

test-audio.zip

Output log:

image pic2

icbaker commented 9 months ago

Does it have no support for this?

I suspect this is the case.

Can you please link to a description of the UNSYNCEDLYRICS tag, along with information about how it should be parsed? I couldn't find details of it where I generally find info about other ID3 tags: https://exiftool.org/TagNames/ID3.html

We are unlikely to prioritise adding support for this ourselves, but would review a high quality PR if you want to implement the support (along with a reference spec for us to read and understand).

lyswhut commented 9 months ago

The field it on ID3 is named: USLT. The official website of ID3 seems to be offline. I found this from the web archive

Unfortunately, I am not an expert in this area and cannot provide PR.

Here are some links that may be helpful: