Skip to content

Commit

Permalink
Add support for MP4 (M4A) rating support via the `moov.udta.meta.ilst…
Browse files Browse the repository at this point in the history
….rate` atom (box)
  • Loading branch information
Borewit committed Nov 4, 2023
1 parent 1c11eb0 commit 4a14da1
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 5 deletions.
13 changes: 9 additions & 4 deletions lib/mp4/MP4Parser.ts
Expand Up @@ -296,14 +296,14 @@ export class MP4Parser extends BasicParser {
return this.parseValueAtom(tagKey, child);

case 'name': // name atom (optional)
case 'mean':
const name = await this.tokenizer.readToken<AtomToken.INameAtom>(new AtomToken.NameAtom(payLoadLength));
tagKey += ':' + name.name;
break;

case 'mean': // name atom (optional)
const mean = await this.tokenizer.readToken<AtomToken.INameAtom>(new AtomToken.NameAtom(payLoadLength));
// console.log(" %s[%s] = %s", tagKey, header.name, mean.name);
tagKey += ':' + mean.name;
case 'rate':
const rate = await this.tokenizer.readToken<AtomToken.INameAtom>(new AtomToken.NameAtom(payLoadLength));
tagKey += ':' + rate.name;
break;

default:
Expand Down Expand Up @@ -342,6 +342,11 @@ export class MP4Parser extends BasicParser {
this.addTag(tagKey, genreStr);
break;

case 'rate':
const rate = new Token.StringType(2, 'ascii').get(dataAtom.value, 0);
this.addTag(tagKey, rate);
break;

default:
// console.log(" reserved-data: name=%s, len=%s, set=%s, type=%s, locale=%s, value{ hex=%s, ascii=%s }",
// header.name, header.length, dataAtom.type.set, dataAtom.type.type, dataAtom.locale, dataAtom.value.toString('hex'), dataAtom.value.toString('ascii'));
Expand Down
18 changes: 17 additions & 1 deletion lib/mp4/MP4TagMapper.ts
@@ -1,5 +1,7 @@
import { CaseInsensitiveTagMap } from '../common/CaseInsensitiveTagMap.js';
import { INativeTagMap } from '../common/GenericTagTypes.js';
import {ITag} from "../type.js";
import {INativeMetadataCollector} from "../common/MetadataCollector.js";

/**
* Ref: https://github.com/sergiomb2/libmp4v2/wiki/iTunesMetadata
Expand Down Expand Up @@ -105,7 +107,8 @@ const mp4TagMap: INativeTagMap = {
hdvd: 'hdVideo',
keyw: 'keywords',
shwm: 'showMovement',
stik: 'stik'
stik: 'stik',
rate: 'rating'
};

export const tagType = 'iTunes';
Expand All @@ -116,4 +119,17 @@ export class MP4TagMapper extends CaseInsensitiveTagMap {
super([tagType], mp4TagMap);
}

protected postMap(tag: ITag, warnings: INativeMetadataCollector): void {

switch (tag.id) {

case 'rate':
tag.value = {
source: undefined,
rating: parseFloat(tag.value) / 100
};
break;
}
}

}
Binary file added test/samples/rating/testcase.m4a
Binary file not shown.
10 changes: 10 additions & 0 deletions test/test-file-mp4.ts
Expand Up @@ -460,4 +460,14 @@ describe('Parse MPEG-4 files with iTunes metadata', () => {
assert.strictEqual('S2E32 : Audio', common.title, 'common.title');
});

it('moov.udta.meta.ilst.rate mapping', async () => {

const filePath = path.join(samplePath, 'rating', 'testcase.m4a');
const {format, common, native} = await mm.parseFile(filePath);

assert.isDefined(common.rating, 'Expect rating property to be present');
assert.equal(common.rating[0].rating, 0.80, 'Vorbis tag rating score of 80%');
assert.equal(mm.ratingToStars(common.rating[0].rating), 4, 'Vorbis tag rating conversion');
});

});

0 comments on commit 4a14da1

Please sign in to comment.