Skip to content

Commit

Permalink
Select cover image from images in metadata.
Browse files Browse the repository at this point in the history
  • Loading branch information
Borewit committed Sep 12, 2020
1 parent 63258b7 commit ba404bb
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 4 deletions.
21 changes: 19 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -219,13 +219,30 @@ orderTags(nativeTags: ITag[]): [tagId: string]: any[]
```

#### ratingToStars function

Can be used to convert the normalized rating value to the 0..5 stars, where 0 an undefined rating, 1 the star the lowest rating and 5 the highest rating.

```ts
ratingToStars(rating: number): number
```
#### selectCover function

Can be used to convert the normalized rating value to the 0..5 stars, where 0 an undefined rating, 1 the star the lowest rating and 5 the highest rating.
Select cover image based on image type field, otherwise the first picture in file.

```ts
ratingToStars(rating: number): number
export function selectCover(pictures?: IPicture[]): IPicture | null
```

```js
import * as mm from 'music-metadata';
(async () => {
const {common} = await mm.parseFile(filePath);
const cover = mm.selectCover(common.picture); // pick the cover image
}
)();
```

### Options
* `duration`: default: `false`, if set to `true`, it will parse the whole media file if required to determine the duration.
* `observer: (update: MetadataEvent) => void;`: Will be called after each change to `common` (generic) tag, or `format` properties.
Expand Down
15 changes: 14 additions & 1 deletion lib/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import * as Stream from 'stream';
import * as strtok3 from 'strtok3/lib/core';

import {ParserFactory} from './ParserFactory';
import { IAudioMetadata, INativeTagDict, IOptions, IPrivateOptions, IRandomReader, ITag } from './type';
import { IAudioMetadata, INativeTagDict, IOptions, IPicture, IPrivateOptions, IRandomReader, ITag } from './type';
import { RandomBufferReader } from './common/RandomBufferReader';
import { APEv2Parser } from './apev2/APEv2Parser';
import { hasID3v1Header } from './id3v1/ID3v1Parser';
Expand Down Expand Up @@ -70,6 +70,19 @@ export function ratingToStars(rating: number): number {
return rating === undefined ? 0 : 1 + Math.round(rating * 4);
}

/**
* Select most likely cover image.
* @param pictures Usually metadata.common.picture
* @return Cover image, if any, otherwise null
*/
export function selectCover(pictures?: IPicture[]): IPicture | null {
return pictures ? pictures.reduce((acc, cur) => {
if (cur.name && cur.name.toLowerCase() in ['front', 'cover', 'cover (front)'])
return cur;
return acc;
}) : null;
}

export async function scanAppendingHeaders(randomReader: IRandomReader, options: IPrivateOptions = {}) {

let apeOffset = randomReader.fileSize;
Expand Down
2 changes: 1 addition & 1 deletion lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export { IAudioMetadata, IOptions, ITag, INativeTagDict, ICommonTagsResult, IFor

const debug = _debug("music-metadata:parser");

export { parseFromTokenizer, parseBuffer, IFileInfo } from './core';
export { parseFromTokenizer, parseBuffer, IFileInfo, selectCover } from './core';

/**
* Parse audio from Node Stream.Readable
Expand Down
34 changes: 34 additions & 0 deletions test/test-common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,40 @@ describe('Convert rating', () => {

});

describe('function selectCover()', () => {

const samplePath = path.join(__dirname, 'samples');

const multiCoverFiles = [
'MusicBrainz - Beth Hart - Sinner\'s Prayer [id3v2.3].V2.mp3',
'MusicBrainz - Beth Hart - Sinner\'s Prayer [id3v2.3].wav',
'MusicBrainz - Beth Hart - Sinner\'s Prayer [id3v2.4].V2.mp3',
'MusicBrainz - Beth Hart - Sinner\'s Prayer [id3v2.4].aiff',
'MusicBrainz - Beth Hart - Sinner\'s Prayer.ape',
'MusicBrainz - Beth Hart - Sinner\'s Prayer.flac',
'MusicBrainz - Beth Hart - Sinner\'s Prayer.m4a',
'MusicBrainz - Beth Hart - Sinner\'s Prayer.ogg',
'id3v2.4.mp3',
'issue-266.flac',
'monkeysaudio.ape'
];

it('Should pick the front cover', async () => {
for (const multiCoverFile of multiCoverFiles) {
const filePath = path.join(samplePath, multiCoverFile);
const {common} = await mm.parseFile(filePath);
assert.isTrue(common.picture.length > 1);
const cover = mm.selectCover(common.picture);
if (cover.type) {
assert.equal(cover.type, 'Cover (front)', 'cover.type');
} else {
assert.equal(cover.data, common.picture[0].data, 'First picture if no type is defined');
}
}
});

});

describe('MimeType', () => {

it('should be able to decode basic MIME-types', () => {
Expand Down

0 comments on commit ba404bb

Please sign in to comment.