From e88d5e4207107fb26d2689ac6609d27931d2ec87 Mon Sep 17 00:00:00 2001 From: Sayem Chowdhury Date: Fri, 5 Mar 2021 20:14:49 +0600 Subject: [PATCH] add album meta tags --- src/metadata-writer/flacmetata.ts | 27 ++++++++++-- src/metadata-writer/id3.ts | 73 +++++++++++++++++++++++-------- src/metadata-writer/index.ts | 18 ++++++-- src/tests/api.ts | 6 +-- src/types/tracks.ts | 4 +- 5 files changed, 97 insertions(+), 31 deletions(-) diff --git a/src/metadata-writer/flacmetata.ts b/src/metadata-writer/flacmetata.ts index 1a9b4aa..7e0f3d3 100644 --- a/src/metadata-writer/flacmetata.ts +++ b/src/metadata-writer/flacmetata.ts @@ -1,35 +1,54 @@ // @ts-ignore import Metaflac from '../lib/metaflac-js'; -import type {trackType} from '../types'; +import type {albumTypePublicApi, trackType} from '../types'; export const writeMetadataFlac = ( buffer: Buffer, track: trackType, + album: albumTypePublicApi, dimension: number, cover?: Buffer | null, ): Buffer => { const flac = new Metaflac(buffer); - flac.setTag('TITLE=' + track.SNG_TITLE); - flac.setTag('ALBUM=' + track.ALB_TITLE); + const RELEASE_YEAR = album.release_date.split('-')[0]; const artists = track.ART_NAME.split( new RegExp(' featuring | feat. | Ft. | ft. | vs | vs. | x | - |, ', 'g'), ).map((a) => a.trim()); + + flac.setTag('TITLE=' + track.SNG_TITLE); + flac.setTag('ALBUM=' + track.ALB_TITLE); + flac.setTag('GENRE=' + album.genres.data[0].name); + flac.setTag('RELEASETYPE=' + album.record_type); flac.setTag('ARTIST=' + artists.join(', ')); + flac.setTag('ALBUMARTIST=' + album.artist.name); + flac.setTag('TRACKNUMBER=' + track.TRACK_NUMBER); if (track.DISK_NUMBER) { flac.setTag('DISCNUMBER=' + track.DISK_NUMBER); } - flac.setTag('LENGTH=' + track.DURATION); flac.setTag('ISRC=' + track.ISRC); + flac.setTag('BARCODE=' + album.upc); + flac.setTag('LABEL=' + album.label); + flac.setTag('LENGTH=' + track.DURATION); flac.setTag('MEDIA=Digital Media'); + flac.setTag('TRACKNUMBER=' + track.TRACK_NUMBER); + flac.setTag('YEAR=' + RELEASE_YEAR); + flac.setTag('DATE=' + album.release_date); if (track.LYRICS) { flac.setTag('LYRICS=' + track.LYRICS.LYRICS_TEXT); } + if (track.EXPLICIT_LYRICS) { + flac.setTag('EXPLICIT=' + track.EXPLICIT_LYRICS); + } if (track.SNG_CONTRIBUTORS) { + flac.setTag(`COPYRIGHT=${RELEASE_YEAR} ${track.SNG_CONTRIBUTORS.main_artist[0]}`); + if (track.SNG_CONTRIBUTORS.publisher) { + flac.setTag('ORGANIZATION=' + track.SNG_CONTRIBUTORS.publisher.join(', ')); + } if (track.SNG_CONTRIBUTORS.composer) { flac.setTag('COMPOSER=' + track.SNG_CONTRIBUTORS.composer.join(', ')); } diff --git a/src/metadata-writer/id3.ts b/src/metadata-writer/id3.ts index e830c6d..808127f 100644 --- a/src/metadata-writer/id3.ts +++ b/src/metadata-writer/id3.ts @@ -1,26 +1,57 @@ // @ts-ignore import id3Writer from 'browser-id3-writer'; -import type {trackType} from '../types'; +import type {albumTypePublicApi, trackType} from '../types'; -export const writeMetadataMp3 = (buffer: Buffer, track: trackType, cover?: Buffer | null): Buffer => { +export const writeMetadataMp3 = ( + buffer: Buffer, + track: trackType, + album: albumTypePublicApi, + cover?: Buffer | null, +): Buffer => { const writer = new id3Writer(buffer); - writer.setFrame('TIT2', track.SNG_TITLE).setFrame('TALB', track.ALB_TITLE); + const RELEASE_YEAR = album.release_date.split('-')[0]; const artists = track.ART_NAME.split( new RegExp(' featuring | feat. | Ft. | ft. | vs | vs. | x | - |, ', 'g'), ).map((a) => a.trim()); - writer.setFrame('TPE2', artists).setFrame('TPE1', [artists.join(', ')]); writer + .setFrame('TIT2', track.SNG_TITLE) + .setFrame('TALB', track.ALB_TITLE) + .setFrame( + 'TCON', + album.genres.data.map((g) => g.name), + ) + .setFrame('TPE1', [artists]) + .setFrame('TPE2', album.artist.name) + .setFrame('TLEN', Number(track.DURATION) * 1000) + .setFrame('TYER', RELEASE_YEAR) + .setFrame('TDAT', album.release_date) .setFrame('TMED', 'Digital Media') .setFrame('TXXX', { description: 'Artists', value: artists.join(', '), }) + .setFrame('TXXX', { + description: 'RELEASETYPE', + value: album.record_type, + }) .setFrame('TXXX', { description: 'ISRC', value: track.ISRC, }) + .setFrame('TXXX', { + description: 'BARCODE', + value: album.upc, + }) + .setFrame('TXXX', { + description: 'LABEL', + value: album.label, + }) + .setFrame('TXXX', { + description: 'COMPILATION', + value: track.ART_PICTURE === 'Various Artists' ? '1' : '0', + }) .setFrame('TXXX', { description: 'SOURCE', value: 'Deezer', @@ -31,30 +62,30 @@ export const writeMetadataMp3 = (buffer: Buffer, track: trackType, cover?: Buffe }); if (track.DISK_NUMBER) { - writer.setFrame('TPOS', track.DISK_NUMBER).setFrame('TXXX', { - description: 'DISCNUMBER', - value: track.DISK_NUMBER, - }); + writer.setFrame('TPOS', track.DISK_NUMBER).setFrame('TRCK', track.TRACK_NUMBER + '/' + album.nb_tracks); } - writer.setFrame('TXXX', { - description: 'LENGTH', - value: track.DURATION, - }); - if (track.SNG_CONTRIBUTORS) { - if (track.SNG_CONTRIBUTORS.composer) { - writer.setFrame('TXXX', { - description: 'COMPOSER', - value: track.SNG_CONTRIBUTORS.composer.join(', '), - }); + writer.setFrame('TCOP', `${RELEASE_YEAR} ${track.SNG_CONTRIBUTORS.main_artist[0]}`); + if (track.SNG_CONTRIBUTORS.publisher) { + writer.setFrame('TPUB', track.SNG_CONTRIBUTORS.publisher.join(', ')); } + if (track.SNG_CONTRIBUTORS.composer) { + writer.setFrame('TCOM', track.SNG_CONTRIBUTORS.composer); + } + if (track.SNG_CONTRIBUTORS.writer) { writer.setFrame('TXXX', { description: 'LYRICIST', value: track.SNG_CONTRIBUTORS.writer.join(', '), }); } + if (track.SNG_CONTRIBUTORS.author) { + writer.setFrame('TXXX', { + description: 'AUTHOR', + value: track.SNG_CONTRIBUTORS.author.join(', '), + }); + } if (track.SNG_CONTRIBUTORS.mixer) { writer.setFrame('TXXX', { description: 'MIXARTIST', @@ -75,6 +106,12 @@ export const writeMetadataMp3 = (buffer: Buffer, track: trackType, cover?: Buffe lyrics: track.LYRICS.LYRICS_TEXT, }); } + if (track.EXPLICIT_LYRICS) { + writer.setFrame('TXXX', { + description: 'EXPLICIT', + value: track.EXPLICIT_LYRICS, + }); + } if (cover) { writer.setFrame('APIC', { diff --git a/src/metadata-writer/index.ts b/src/metadata-writer/index.ts index 1e7c6f7..02d169c 100644 --- a/src/metadata-writer/index.ts +++ b/src/metadata-writer/index.ts @@ -1,8 +1,8 @@ import {downloadAlbumCover} from './abumCover'; import {getTrackLyrics} from './getTrackLyrics'; -// @ts-ignore import {writeMetadataMp3} from './id3'; import {writeMetadataFlac} from './flacmetata'; +import {getAlbumInfoPublicApi} from '../api'; import type {trackType} from '../types'; /** @@ -12,14 +12,24 @@ import type {trackType} from '../types'; * @param {Number} albumCoverSize album cover size in pixel */ export const addTrackTags = async (trackBuffer: Buffer, track: trackType, albumCoverSize = 1000): Promise => { - const [cover, lyrics] = await Promise.all([downloadAlbumCover(track, albumCoverSize), getTrackLyrics(track)]); + const [cover, lyrics, album] = await Promise.all([ + downloadAlbumCover(track, albumCoverSize), + getTrackLyrics(track), + getAlbumInfoPublicApi(track.ALB_ID), + ]); if (lyrics) { track.LYRICS = lyrics; } + if (track.ART_NAME.toLowerCase() === 'various') { + track.ART_NAME = 'Various Artists'; + } + album.record_type = + album.record_type === 'ep' ? 'EP' : album.record_type.charAt(0).toUpperCase() + album.record_type.slice(1); + const isFlac = trackBuffer.slice(0, 4).toString('ascii') === 'fLaC'; return isFlac - ? writeMetadataFlac(trackBuffer, track, albumCoverSize, cover) - : writeMetadataMp3(trackBuffer, track, cover); + ? writeMetadataFlac(trackBuffer, track, album, albumCoverSize, cover) + : writeMetadataMp3(trackBuffer, track, album, cover); }; diff --git a/src/tests/api.ts b/src/tests/api.ts index 11c7b9b..9144596 100644 --- a/src/tests/api.ts +++ b/src/tests/api.ts @@ -152,7 +152,7 @@ if (process.env.CI) { const trackWithMetadata = await api.addTrackTags(decryptedTrack, track, 500); t.true(Buffer.isBuffer(trackWithMetadata)); - t.is(trackWithMetadata.length, 3628837); + t.is(trackWithMetadata.length, 3629256); }); test('DOWNLOAD TRACK320 & ADD METADATA', async (t) => { @@ -170,7 +170,7 @@ if (process.env.CI) { const trackWithMetadata = await api.addTrackTags(decryptedTrack, track, 500); t.true(Buffer.isBuffer(trackWithMetadata)); - t.is(trackWithMetadata.length, 9023019); + t.is(trackWithMetadata.length, 9023438); }); test('DOWNLOAD TRACK1411 & ADD METADATA', async (t) => { @@ -188,6 +188,6 @@ if (process.env.CI) { const trackWithMetadata = await api.addTrackTags(decryptedTrack, track, 500); t.true(Buffer.isBuffer(trackWithMetadata)); - t.is(trackWithMetadata.length, 25453167); + t.is(trackWithMetadata.length, 25453375); }); } diff --git a/src/types/tracks.ts b/src/types/tracks.ts index 98834e2..3778548 100644 --- a/src/types/tracks.ts +++ b/src/types/tracks.ts @@ -25,8 +25,8 @@ interface songType { ALB_TITLE: string; // 'Discovery' ALB_PICTURE: string; // '2e018122cb56986277102d2041a592c8' ARTISTS: artistType[]; - ART_ID: '27'; - ART_NAME: 'Daft Punk'; + ART_ID: string; // '27' + ART_NAME: string; // 'Daft Punk' ARTIST_IS_DUMMY: boolean; // false ART_PICTURE: string; //'f2bc007e9133c946ac3c3907ddc5d2ea' DATE_START: string; // '0000-00-00'