Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optionally yield metadata before first frame (feature request) #25

Open
HDegroote opened this issue Apr 30, 2023 · 4 comments
Open

Optionally yield metadata before first frame (feature request) #25

HDegroote opened this issue Apr 30, 2023 · 4 comments
Labels
enhancement New feature or request

Comments

@HDegroote
Copy link

Context: I'm using this library to split a FLAC file into frames, but I also need the metadata (all bytes before the first frame).

From what I understand, the current code simply drops all bytes before the first frame. Would you be open to adding an option which, if set, yields all those bytes as the first chunk?

By accessing the library internals, I can use this workaround:

    const parser = new CodecParser('audio/flac')
    let nrMetadataBytes = null
    
    for await (const entry of stream) {
      for (const frame of parser.parseChunk(entry)) {
        if (nrMetadataBytes === null) { // First frame
          nrMetadataBytes = parser._currentReadPosition - frame.data.length
        }
        // ... process the normal frames
    }

But it's pretty ugly and inconvenient (I have to open a new readStream to actually read those bytes since they're already skipped)

Willing to create a PR if you're open to adding this (feel free to close if not)

@eshaz
Copy link
Owner

eshaz commented May 1, 2023

I think this would be a good enhancement. It would make sense to for this library actually parse the metadata and provide this data similar to how the audio header and data is returned. The parser would need to follow all of the conventions / formatting defined here.

I also have another feature in the pipeline to return ID3v2 metadata #16, so I'd also include that in any design change for FLAC metadata. I'm not entirely sure how this would fit into the current design, but I have a few ideas:

The metadata could either be added to the first frame returned

//1st yield
FLACFrame {
  data: ...
  header: ...
  metadata: [
    FLACMetadata {
      type: "VORBIS_COMMENTS",
      ARTIST: "Some Artist",
      TITLE: "Some Title"
      data: Uint8Array
    },
    FLACMetadata {
      type: "PICTURE",
      pictureType: "Cover (front)",
      data: Uint8Array
    }
  ]
}

or, it could be returned in separate objects before the first audio frame (could be controlled by an instance option).

// 1st yield
FLACMetadata {
  type: "tags",
  ARTIST: "Some Artist",
  TITLE: "Some Title"
  data: Uint8Array
}

// 2nd yield
FLACMetadata {
  type: "picture",
  pictureType: "Cover (front)",
  data: Uint8Array
}

// 3rd yield
FLACFrame {
  type: "audio",
  data: ...
  header: ...
}

@eshaz eshaz added the enhancement New feature or request label May 1, 2023
@HDegroote
Copy link
Author

There are already a few libraries out there which parse metadata, so another option is to use those. Could be either directly in this module, or orthogonally.

My initial idea was to get out the metadata block in raw bytes using this library, and to then use one of those libraries to parse the raw bytes to metadata blocks.

For example, the music-metadata module has support for parsing FLAC metadata (as well as many other formats) https://github.com/Borewit/music-metadata/blob/3e535ae97cda00291c39b166310339d4968c8868/lib/flac/FlacParser.ts. I checked, and just passing it the metadata bytes seems to work well (although they need to be passed as a ReadableStream).

@eshaz
Copy link
Owner

eshaz commented May 2, 2023

It might be a while before I implement this, but I think the next set of features for this library will be some level of metadata parsing.

In the meantime, could you use ReadableStream.tee() to pipe the data both to your metadata library and CodecParser? That should let both libraries consume the same data, without having to re-read the data after it's gone through CodecParser.

@HDegroote
Copy link
Author

No worries, thanks for the quick replies!

Yeah, tee-ing the stream and passing to both libraries is a cleaner solution than what I'm currently doing.

I haven't yet found a metadata library that also returns the raw bytes, but it should be pretty straightforward to adapt an existing one, so all good here, and I can easily work around this in the mean time.

Thanks for the useful library!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants