mirror of
https://github.com/arcodange-org/mediabunny.git
synced 2026-10-01 21:03:46 +02:00
Fix WAV files with embedded ID3 metadata returning empty tags (#110)
* Read ID3v2 tags from WAV file * remove js import Co-authored-by: David P. <[email protected]> * revert slicing in wave-demuxer.ts and add id3.ts for further sharing * Add `writeId3Tag` to the `WavOutputFormat` constructor options * add more context in private and public APIs that it's non-standard * compare actual values in the test with real file * remove unnecesarry double slice requesting * trim test audio file (i tried my best to preserve ID3, including artwork) * Couple of code cleanups * const -> using * Fix linting errors --------- Co-authored-by: David P. <[email protected]>
This commit is contained in:
co-authored by
David P.
parent
cab8319051
commit
6aee4e6a6a
@@ -567,3 +567,99 @@ test('Conversion metadata tags, modified', async () => {
|
||||
expect(readTags.artist).toBe(songMetadata.artist);
|
||||
expect(Object.keys(readTags.raw!).length).toBe(2);
|
||||
});
|
||||
|
||||
test('Read ID3v2 tags from WAV file', async () => {
|
||||
const filePath = path.join(import.meta.dirname, '../public/glitch-hop-is-dead.wav');
|
||||
|
||||
using input = new Input({
|
||||
source: new FilePathSource(filePath),
|
||||
formats: ALL_FORMATS,
|
||||
});
|
||||
|
||||
const tags = await input.getMetadataTags();
|
||||
|
||||
const expectedTitle = 'Glitch Hop Is Dead';
|
||||
const expectedArtist = 'GRiZ';
|
||||
const expectedTrackNumber = 19;
|
||||
|
||||
// Specific expectations for the test WAV file
|
||||
expect(tags.title).toBe(expectedTitle);
|
||||
expect(tags.artist).toBe(expectedArtist);
|
||||
expect(tags.trackNumber).toBe(expectedTrackNumber);
|
||||
|
||||
if (!tags.images) {
|
||||
throw new Error('No images found in the file');
|
||||
}
|
||||
|
||||
const frontCover = tags.images[0];
|
||||
|
||||
if (!frontCover) {
|
||||
throw new Error('No front cover found in the file');
|
||||
}
|
||||
|
||||
expect(frontCover.kind).toBe('coverFront');
|
||||
expect(frontCover.mimeType).toBe('image/jpg');
|
||||
expect(frontCover.data).toBeInstanceOf(Uint8Array);
|
||||
expect(frontCover.data.length).toBeGreaterThan(0);
|
||||
|
||||
if (!tags.raw) {
|
||||
throw new Error('No raw tags found in the file');
|
||||
}
|
||||
|
||||
expect(tags.raw['TIT2']).toBe(expectedTitle); // Title
|
||||
expect(tags.raw['TPE1']).toBe(expectedArtist); // Artist
|
||||
expect(tags.raw['TRCK']).toBe(String(expectedTrackNumber)); // Track number
|
||||
expect(tags.raw['APIC']).toBeInstanceOf(Uint8Array);
|
||||
});
|
||||
|
||||
test('Write WAV with ID3 tags', async () => {
|
||||
const output = new Output({
|
||||
target: new BufferTarget(),
|
||||
format: new WavOutputFormat({ metadataFormat: 'id3' }),
|
||||
});
|
||||
|
||||
output.setMetadataTags(songMetadata);
|
||||
|
||||
const dummyTrack = createDummyAudioTrack('pcm-f32', output);
|
||||
|
||||
await output.start();
|
||||
await dummyTrack.addPacket();
|
||||
await output.finalize();
|
||||
|
||||
using input = new Input({
|
||||
source: new BufferSource(output.target.buffer!),
|
||||
formats: ALL_FORMATS,
|
||||
});
|
||||
|
||||
const readTags = await input.getMetadataTags();
|
||||
|
||||
expect(readTags.title).toBe(songMetadata.title);
|
||||
expect(readTags.artist).toBe(songMetadata.artist);
|
||||
expect(readTags.album).toBe(songMetadata.album);
|
||||
expect(readTags.albumArtist).toBe(songMetadata.albumArtist);
|
||||
expect(readTags.trackNumber).toBe(songMetadata.trackNumber);
|
||||
expect(readTags.discNumber).toBe(songMetadata.discNumber);
|
||||
expect(readTags.genre).toBe(songMetadata.genre);
|
||||
expect(readTags.comment).toBe(songMetadata.comment);
|
||||
expect(readTags.lyrics).toBe(songMetadata.lyrics);
|
||||
|
||||
expect(readTags.date).toBeDefined();
|
||||
|
||||
expect(readTags.raw).toBeDefined();
|
||||
if (readTags.raw) {
|
||||
// Verify RIFF INFO tags are not present
|
||||
expect(readTags.raw['INAM']).toBeUndefined();
|
||||
|
||||
// Verify ID3 tags are also present
|
||||
expect(readTags.raw['TIT2']).toBe(songMetadata.title);
|
||||
expect(readTags.raw['TPE1']).toBe(songMetadata.artist);
|
||||
expect(readTags.raw['TALB']).toBe(songMetadata.album);
|
||||
expect(readTags.raw['TPE2']).toBe(songMetadata.albumArtist);
|
||||
expect(readTags.raw['TCON']).toBe(songMetadata.genre);
|
||||
expect(readTags.raw['COMM']).toBeDefined();
|
||||
expect(readTags.raw['USLT']).toBeDefined();
|
||||
expect(readTags.raw['TRCK']).toBe(`${songMetadata.trackNumber}/${songMetadata.tracksTotal}`);
|
||||
expect(readTags.raw['TPOS']).toBe(`${songMetadata.discNumber}/${songMetadata.discsTotal}`);
|
||||
expect(readTags.raw['TDRC']).toBeDefined();
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user