From d06111add72e4fb6bd4618c6e447ddece0efa59f Mon Sep 17 00:00:00 2001 From: Borewit Date: Sun, 10 Nov 2024 14:24:17 +0100 Subject: [PATCH] Include numberOfSamples for CBR encoded MP3 --- lib/mpeg/MpegParser.ts | 5 +++-- test/test-file-mp3.ts | 24 +++++++++++++++++++----- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/lib/mpeg/MpegParser.ts b/lib/mpeg/MpegParser.ts index e25b4c891..6e13d8bc5 100644 --- a/lib/mpeg/MpegParser.ts +++ b/lib/mpeg/MpegParser.ts @@ -357,12 +357,13 @@ export class MpegParser extends AbstractID3Parser { if (format.codecProfile && format.codecProfile[0] === 'V') { this.metadata.setFormat('bitrate', mpegSize * 8 / format.duration); } - } else if (this.tokenizer.fileInfo.size && format.codecProfile === 'CBR') { + } + if (this.tokenizer.fileInfo.size && format.codecProfile === 'CBR') { const mpegSize = this.tokenizer.fileInfo.size - this.mpegOffset - (hasID3v1 ? 128 : 0); if (this.frame_size !== null && this.samplesPerFrame !== null) { const numberOfSamples = Math.round(mpegSize / this.frame_size) * this.samplesPerFrame; this.metadata.setFormat('numberOfSamples', numberOfSamples); - if (format.sampleRate) { + if (format.sampleRate && !format.duration) { const duration = numberOfSamples / format.sampleRate; debug("Calculate CBR duration based on file size: %s", duration); this.metadata.setFormat('duration', duration); diff --git a/test/test-file-mp3.ts b/test/test-file-mp3.ts index f95937886..3b093f792 100644 --- a/test/test-file-mp3.ts +++ b/test/test-file-mp3.ts @@ -253,11 +253,11 @@ describe('Parse MP3 files', () => { describe('duration=false', () => { - Parsers + Parsers.slice(0, 1) .forEach(parser => { it(parser.description, async function(){ - const metadata = await parser.initParser(() => this.skip(), filePath, 'audio/mpeg', {duration: false}); - assert.isUndefined(metadata.format.duration, 'Don\'t expect a duration'); + const { format } = await parser.initParser(() => this.skip(), filePath, 'audio/mpeg', {duration: false}); + assert.isUndefined(format.duration, 'Don\'t expect a duration'); }); }); }); @@ -269,8 +269,9 @@ describe('Parse MP3 files', () => { Parsers .forEach(parser => { it(parser.description, async function(){ - const metadata = await parser.initParser(() => this.skip(), filePath, 'audio/mpeg', {duration: true}); - assert.approximately(metadata.format.duration, durationSleepAwayMp3, 1 / 10, 'Expect a duration'); + const { format } = await parser.initParser(() => this.skip(), filePath, 'audio/mpeg', {duration: true}); + assert.approximately(format.duration, durationSleepAwayMp3, 1 / 10, 'Expect a duration'); + assert.strictEqual(format.numberOfSamples, 8831232, 'format.numberOfSamples'); }); }); }); @@ -368,4 +369,17 @@ describe('Parse MP3 files', () => { }); + describe('Expect format.numberOfSamples', async () => { + [false, true].forEach(durationFlag => { + it(`duration=${durationFlag}`, async () => { + const filePath = path.join(mp3SamplePath, 'lame-peak.mp3'); + const {format} = await mm.parseFile(filePath, {duration: durationFlag}); + + assert.strictEqual(format.container, 'MPEG'); + assert.strictEqual(format.codec, 'MPEG 1 Layer 3', '(format.codec'); + assert.strictEqual(format.numberOfSamples, 5760,'format.numberOfSamples'); + }); + }); + }); + });