1
0
mirror of synced 2026-05-22 22:53:20 +00:00
Files
music-metadata/lib/type.ts
T

776 lines
14 KiB
TypeScript

import type { TagType } from './common/GenericTagTypes.js';
import type { IFooter } from './apev2/APEv2Token.js';
import type { TrackType } from './matroska/types.js';
import type { LyricsContentType, TimestampFormat } from './id3v2/ID3v2Token.js';
export { TrackType, TrackTypeValueToKeyMap } from './matroska/types.js';
export { LyricsContentType, TimestampFormat } from './id3v2/ID3v2Token.js';
export type AnyTagValue = unknown;
/**
* Attached picture, typically used for cover art
*/
export interface IPicture {
/**
* Image mime type
*/
format: string;
/**
* Image data
*/
data: Uint8Array;
/**
* Optional description
*/
description?: string;
/**
* Picture type
*/
type?: string;
/**
* File name
*/
name?: string;
}
/**
* Abstract interface to access rating information
*/
export interface IRating {
/**
* Rating source, could be an e-mail address
*/
source?: string;
/**
* Rating [0..1]
*/
rating?: number;
}
export interface ICommonTagsResult {
track: { no: number | null, of: number | null };
disk: { no: number | null, of: number | null };
/**
* Release year
*/
year?: number;
/**
* Track title
*/
title?: string;
/**
* Track, maybe several artists written in a single string.
*/
artist?: string;
/**
* Track artists, aims to capture every artist in a different string.
*/
artists?: string[];
/**
* Track album artist/s. Contains the first album artist if multiple tags exist, or maybe several album artists written in a single string.
*/
albumartist?: string;
/**
* Track album artists, aims to capture every album artist in a different string.
*/
albumartists?: string[];
/**
* Album title
*/
album?: string;
/**
* Date
*/
date?: string;
/**
* Original release date
*/
originaldate?: string;
/**
* Original release year
*/
originalyear?: number;
/**
* Release date
*/
releasedate?: string;
/**
* List of comments
*/
comment?: IComment[];
/**
* Genre
*/
genre?: string[];
/**
* Embedded album art
*/
picture?: IPicture[];
/**
* Track composer
*/
composer?: string[];
/**
* Synchronized lyrics
*/
lyrics?: ILyricsTag[];
/**
* Album title, formatted for alphabetic ordering
*/
albumsort?: string;
/**
* Track title, formatted for alphabetic ordering
*/
titlesort?: string;
/**
* The canonical title of the work
*/
work?: string;
/**
* Track artist, formatted for alphabetic ordering
*/
artistsort?: string;
/**
* Album artist, formatted for alphabetic ordering
*/
albumartistsort?: string;
/**
* Composer, formatted for alphabetic ordering
*/
composersort?: string;
/**
* Lyricist(s)
*/
lyricist?: string[];
/**
* Writer(s)
*/
writer?: string[];
/**
* Conductor(s)
*/
conductor?: string[];
/**
* Remixer(s)
*/
remixer?: string[];
/**
* Arranger(s)
*/
arranger?: string[];
/**
* Engineer(s)
*/
engineer?: string[];
/**
* Publisher(s)
*/
publisher?: string[];
/**
* Producer(s)
*/
producer?: string[];
/**
* Mix-DJ(s)
*/
djmixer?: string[];
/**
* Mixed by
*/
mixer?: string[];
technician?: string[];
label?: string[];
grouping?: string;
subtitle?: string[];
description?: string[];
longDescription?: string;
discsubtitle?: string[];
totaltracks?: string;
totaldiscs?: string;
movementTotal?: number;
compilation?: boolean;
rating?: IRating[];
bpm?: number;
/**
* Keywords to reflect the mood of the audio, e.g. 'Romantic' or 'Sad'
*/
mood?: string;
/**
* Release format, e.g. 'CD'
*/
media?: string;
/**
* Release catalog number(s)
*/
catalognumber?: string[];
/**
* TV show title
*/
tvShow?: string;
/**
* TV show title, formatted for alphabetic ordering
*/
tvShowSort?: string;
/**
* TV season title sequence number
*/
tvSeason?: number;
/**
* TV Episode sequence number
*/
tvEpisode?: number;
/**
* TV episode ID
*/
tvEpisodeId?: string,
/**
* TV network
*/
tvNetwork?: string,
podcast?: boolean;
podcasturl?: string;
releasestatus?: string;
releasetype?: string[];
releasecountry?: string;
script?: string;
language?: string;
copyright?: string;
license?: string;
encodedby?: string;
encodersettings?: string;
gapless?: boolean;
barcode?: string; // ToDo: multiple??
// International Standard Recording Code
isrc?: string[];
asin?: string;
musicbrainz_recordingid?: string;
musicbrainz_trackid?: string;
musicbrainz_albumid?: string;
musicbrainz_artistid?: string[];
musicbrainz_albumartistid?: string[];
musicbrainz_releasegroupid?: string;
musicbrainz_workid?: string;
musicbrainz_trmid?: string;
musicbrainz_discid?: string;
acoustid_id?: string;
acoustid_fingerprint?: string;
musicip_puid?: string;
musicip_fingerprint?: string;
website?: string;
'performer:instrument'?: string[];
averageLevel?: number;
peakLevel?: number;
notes?: string[];
originalalbum?: string;
originalartist?: string;
// Discogs:
discogs_artist_id?: number[];
discogs_release_id?: number;
discogs_label_id?: number;
discogs_master_release_id?: number;
discogs_votes?: number;
discogs_rating?: number;
/**
* Track gain ratio [0..1]
*/
replaygain_track_gain_ratio?: number;
/**
* Track peak ratio [0..1]
*/
replaygain_track_peak_ratio?: number;
/**
* Track gain ratio
*/
replaygain_track_gain?: IRatio;
/**
* Track peak ratio
*/
replaygain_track_peak?: IRatio;
/**
* Album gain ratio
*/
replaygain_album_gain?: IRatio;
/**
* Album peak ratio
*/
replaygain_album_peak?: IRatio;
/**
* minimum & maximum global gain values across a set of files scanned as an album
*/
replaygain_undo?: {
leftChannel: number,
rightChannel: number
};
/**
* minimum & maximum global gain values across a set of file
*/
replaygain_track_minmax?: number[];
/**
* minimum & maximum global gain values across a set of files scanned as an album
*/
replaygain_album_minmax?: number[];
/**
* The initial key of the music in the file, e.g. "A Minor".
* Ref: https://docs.microsoft.com/en-us/windows/win32/wmformat/wm-initialkey
*/
key?: string;
/**
* Podcast Category
*/
category?: string[];
/**
* iTunes Video Quality
*
* 2: Full HD
* 1: HD
* 0: SD
*/
hdVideo?: number;
/**
* Podcast Keywords
*/
keywords?: string[];
/**
* Movement
*/
movement?: string;
/**
* Movement Index/Total
*/
movementIndex: { no: number | null, of: number | null };
/**
* Podcast Identifier
*/
podcastId?: string;
/**
* Show Movement
*/
showMovement?: boolean;
/**
* iTunes Media Type
*
* 1: Normal
* 2: Audiobook
* 6: Music Video
* 9: Movie
* 10: TV Show
* 11: Booklet
* 14: Ringtone
*
* https://github.com/sergiomb2/libmp4v2/wiki/iTunesMetadata#user-content-media-type-stik
*/
stik?: number;
playCounter?: number;
}
export interface IRatio {
/**
* [0..1]
*/
ratio: number;
/**
* Decibel
*/
dB: number;
}
export type FormatId =
'container'
| 'duration'
| 'bitrate'
| 'sampleRate'
| 'bitsPerSample'
| 'codec'
| 'tool'
| 'codecProfile'
| 'lossless'
| 'numberOfChannels'
| 'numberOfSamples'
| 'audioMD5'
| 'chapters'
| 'modificationTime'
| 'creationTime'
| 'trackPeakLevel'
| 'trackGain'
| 'albumGain'
| 'hasAudio'
| 'hasVideo';
export interface IAudioTrack {
samplingFrequency?: number;
outputSamplingFrequency?: number;
channels?: number;
channelPositions?: Uint8Array;
bitDepth?: number;
}
export interface IVideoTrack {
flagInterlaced?: boolean;
stereoMode?: number;
pixelWidth?: number;
pixelHeight?: number;
displayWidth?: number;
displayHeight?: number;
displayUnit?: number;
aspectRatioType?: number;
colourSpace?: Uint8Array;
gammaValue?: number;
}
export interface ITrackInfo {
type?: TrackType;
codecName?: string;
codecSettings?: string;
flagEnabled?: boolean;
flagDefault?: boolean;
flagLacing?: boolean;
name?: string;
language?: string;
audio?: IAudioTrack;
video?: IVideoTrack;
}
export interface IFormat {
readonly trackInfo: ITrackInfo[]
/**
* E.g.: 'flac'
*/
readonly container?: string, // ToDo: make mandatory
/**
* List of tags found in parsed audio file
*/
readonly tagTypes: TagType[],
/**
* Duration in seconds
*/
readonly duration?: number,
/**
* Number bits per second of encoded audio file
*/
readonly bitrate?: number,
/**
* Sampling rate in Samples per second (S/s)
*/
readonly sampleRate?: number,
/**
* Audio bit depth
*/
readonly bitsPerSample?: number,
/**
* Encoder brand, e.g.: LAME3.99r
*/
readonly tool?: string,
/**
* Encoder name / compressionType, e.g.: 'PCM', 'ITU-T G.711 mu-law'
*/
readonly codec?: string,
/**
* Codec profile
*/
readonly codecProfile?: string,
readonly lossless?: boolean,
/**
* Number of audio channels
*/
readonly numberOfChannels?: number,
/**
* Number of samples frames.
* One sample contains all channels
* The duration is: numberOfSamples / sampleRate
*/
readonly numberOfSamples?: number
/**
* 16-byte MD5 of raw audio
*/
readonly audioMD5?: Uint8Array;
/**
* Chapters in audio stream
*/
readonly chapters?: IChapter[]
/**
* Time file was created
*/
readonly creationTime?: Date;
/**
* Time file was modified
*/
readonly modificationTime?: Date;
readonly trackGain?: number;
readonly trackPeakLevel?: number;
readonly albumGain?: number;
/**
* Indicates if the audio files contains an audio stream
*/
hasAudio?: boolean;
/**
* Indicates if the media files contains a video stream
*/
hasVideo?: boolean;
}
export interface ITag {
id: string;
value: AnyTagValue;
}
export interface IUrl {
url: string;
description: string;
}
export interface IChapter {
/**
* Internal chapter reference
*/
id?: string;
/**
* Chapter title
*/
title: string;
/**
* URL
*/
url?: IUrl;
/**
* Audio offset in sample number, 0 is the first sample.
* Duration offset is sampleOffset / format.sampleRate
*/
sampleOffset?: number;
/**
* Timestamp where the chapter starts
* Chapter timestamp is start/timeScale in seconds.
*/
start: number;
/**
* Timestamp where the chapter end
* Chapter timestamp is start/timeScale in seconds.
*/
end?: number;
/**
* Time value that indicates the timescale for chapter tracks, the number of time units that pass per second in its time coordinate system.
*/
timeScale?: number;
/**
* Picture
*/
image?: IPicture;
}
/**
* Flat list of tags
*/
export interface INativeTags {
[tagType: string]: ITag[];
}
/**
* Tags ordered by tag-ID
*/
export interface INativeTagDict {
[tagId: string]: AnyTagValue[];
}
export interface INativeAudioMetadata {
format: IFormat,
native: INativeTags
quality: IQualityInformation;
}
export interface IQualityInformation {
/**
* Warnings
*/
warnings: IParserWarning[];
}
export interface IParserWarning {
message: string;
}
export interface IAudioMetadata extends INativeAudioMetadata {
/**
* Metadata, form independent interface
*/
common: ICommonTagsResult;
}
/**
* Corresponds with parser module name
*/
export type ParserType =
'mpeg'
| 'apev2'
| 'mp4'
| 'asf'
| 'flac'
| 'ogg'
| 'aiff'
| 'wavpack'
| 'riff'
| 'musepack'
| 'dsf'
| 'dsdiff'
| 'adts'
| 'matroska'
;
export interface IOptions {
/**
* default: `false`, if set to `true`, it will parse the whole media file if required to determine the duration.
*/
duration?: boolean;
/**
* default: `false`, if set to `true`, it will skip parsing covers.
*/
skipCovers?: boolean;
/**
* default: `false`, if set to `true`, it will not search all the entire track for additional headers.
* Only recommenced to use in combination with streams.
*/
skipPostHeaders?: boolean;
/**
* default: `false`, if set to `true`, it will include MP4 chapters
*/
includeChapters?: boolean;
/**
* Set observer for async callbacks to common or format.
*/
observer?: Observer;
/**
* In Matroska based files, use the _SeekHead_ element index to skip _segment/cluster_ elements.
* By default, disabled
* Can have a significant performance impact if enabled.
* Possible side effect can be that certain metadata maybe skipped, depending on the index.
* If there is no _SeekHead_ element present in the Matroska file, this flag has no effect
* Ref: https://www.matroska.org/technical/diagram.html
*/
mkvUseIndex?: boolean;
}
export interface IApeHeader extends IOptions {
/**
* Offset of APE-header
*/
offset: number;
/**
* APEv1 / APEv2 header offset
*/
footer: IFooter;
}
export interface IPrivateOptions extends IOptions {
apeHeader?: IApeHeader;
}
export interface IMetadataEventTag {
/**
* Either `common` if it is a generic tag event, or `format` for format related updates
*/
type: 'common' | 'format';
/**
* Tag id
*/
id: keyof ICommonTagsResult | FormatId;
/**
* Tag value
*/
value: AnyTagValue;
}
/**
* Event definition send after each change to common/format metadata change to observer.
*/
export interface IMetadataEvent {
/**
* Tag which has been updated.
*/
tag: IMetadataEventTag;
/**
* Metadata model including the attached tag
*/
metadata: IAudioMetadata;
}
export type Observer = (update: IMetadataEvent) => void;
export interface ILyricsText {
text: string;
timestamp?: number;
}
export interface IComment {
descriptor?: string;
language?: string;
text?: string;
}
export interface ILyricsTag extends IComment {
contentType: LyricsContentType;
timeStampFormat: TimestampFormat;
/**
* Un-synchronized lyrics
*/
text?: string;
/**
* Synchronized lyrics
*/
syncText: ILyricsText[];
}