Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up

Stream and file based music metadata parser for node. Supporting a wide range of audio and tag formats.

License

NotificationsYou must be signed in to change notification settings

Borewit/music-metadata

Repository files navigation

Node.js CINPM versionnpm downloadsCoverage StatusCodacy BadgeCodeQLDeepScan gradeKnown VulnerabilitiesDiscord

music-metadata

Key features:

  • Comprehensive Format Support: Supports popular audio formats like MP3, MP4, FLAC, Ogg, WAV, AIFF, and more.
  • Extensive Metadata Extraction: Extracts detailed metadata, including ID3v1, ID3v2, APE, Vorbis, and iTunes/MP4 tags.
  • Streaming Support: Efficiently handles large audio files by reading metadata from streams, making it suitable for server-side and browser-based applications.
  • Promise-Based API: Provides a modern, promise-based API for easy integration into asynchronous workflows.
  • Cross-Platform: Works in bothNode.js and browser environments with the help of bundlers likeWebpack orRollup.

Themusic-metadata module is ideal for developers working on media applications, music players, or any project that requires access to detailed audio file metadata.

Compatibility

Module: version 8 migrated fromCommonJS topure ECMAScript Module (ESM).The distributed JavaScript codebase is compliant with theECMAScript 2020 (11th Edition) standard.

This module requires aNode.js ≥ 18 engine.It can also be used in a browser environment when bundled with a module bundler.

Support the Project

If you find this project useful and would like to support its development, consider sponsoring or contributing:

Features

Support for audio file types

Audio formatDescriptionWiki
AIFF / AIFF-CAudio Interchange File Format🔗Apple rainbow logo
AACADTS / Advanced Audio Coding🔗AAC logo
APEMonkey's Audio🔗Monkey's Audio logo
ASFAdvanced Systems Format🔗
BWFBroadcast Wave Format🔗
DSDIFFPhilips DSDIFF🔗DSD logo
DSFSony's DSD Stream File🔗DSD logo
FLACFree Lossless Audio Codec🔗FLAC logo
MP2MPEG-1 Audio Layer II🔗
MatroskaMatroska (EBML), mka, mkv🔗Matroska logo
MP3MPEG-1 / MPEG-2 Audio Layer III🔗MP3 logo
MPCMusepack SV7🔗musepack logo
MPEG 4mp4, m4a, m4v🔗mpeg 4 logo
OggOpen container format🔗Ogg logo
Opus🔗Opus logo
Speex🔗Speex logo
Theora🔗Theora logo
VorbisVorbis audio compression🔗Vorbis logo
WAVRIFF WAVE🔗
WebMwebm🔗Matroska logo
WVWavPack🔗WavPack logo
WMAWindows Media Audio🔗Windows Media logo

Supported tag headers

Following tag header formats are supported:

Following lyric formats are supported:

  • LRC
  • Synchronized lyrics (SYLT)
  • Unsynchronized lyrics (USULT)

Support forMusicBrainz tags as written byPicard.ReplayGain tags are supported.

Audio format & encoding details

Support for encoding / format details:

Online demo's

Usage

Installation

Install usingnpm:

npm install music-metadata

or usingyarn:

yarn add music-metadata

API Documentation

Overview

Node.js specific functions to read an audio file or stream:

  1. File Parsing: Parse audio files directly from the filesystem using theparseFile function
  2. Stream Parsing: Parse audio metadata from a Node.jsReadable stream using theparseStream function.

Cross-platform functions available to read an audio file or stream:

There are multiple ways to parse (read) audio tracks:

  1. Web Stream Parsing: Parse audio data from a web-compatibleReadableStream using theparseWebStream function.
  2. Blob Parsing: Parse audio metadata from a (Web API)Blob orFile using theparseBlob function.
  3. Buffer Parsing: Parse audio metadata from aUint8Array orBuffer using theparseBuffer function.
  4. Tokenizer Parsing: Use a custom or third-partystrtok3ITokenizer to parse using theparseFromTokenizer function.

Note

Direct file access in Node.js is generally faster because it can 'jump' to various parts of the file without reading intermediate data.

Node.js specific function

These functions are tailored for Node.js environments and leverage Node.js-specific APIs,making them incompatible with browser-based JavaScript engines.

parseFile function

TheparseFile function is intended for extracting metadata from audio files on the local filesystem in a Node.js environment.It reads the specified file, parses its audio metadata, and returns a promise that resolves with this information.

Syntax
parseFile(filePath: string,options?:IOptions):Promise<IAudioMetadata>
Parameters
  • filePath:string

    The path to the media file from which metadata should be extracted.This should be a valid path to an audio file on the local filesystem.

  • options:IOptions (optional)

    An optional configuration object that allows customization of the parsing process.These options can include whether to calculate the file's duration, skip embedded cover art,or other parsing behaviors.

Returns
  • Promise<IAudioMetadata>:

    A promise that resolves to an IAudioMetadata object containing metadata about the audio file.The metadata includes details such as the file format, codec, duration, bit rate, and any embedded tags like album, artist, or track information.

Usage Notes
  • This function isNode.js-only and relies on Node.js-specific APIs to access the filesystem.

  • For browser environments, consider using theparseBlob to parseFile object objects.

Example:

The following example demonstrates how to use the parseFile function to read metadata from an audio file:

import{parseFile}from'music-metadata';import{inspect}from'util';(async()=>{try{constfilePath='../music-metadata/test/samples/MusicBrainz - Beth Hart - Sinner\'s Prayer [id3v2.3].V2.mp3';constmetadata=awaitparseFile(filePath);// Output the parsed metadata to the console in a readable formatconsole.log(inspect(metadata,{showHidden:false,depth:null}));}catch(error){console.error('Error parsing metadata:',error.message);}})();

parseStream function

The parseStream function is used to parse metadata from an audio track provided as a Node.jsReadable stream.This is particularly useful for processing audio data that is being streamed or piped from another source, such as a web server or file system.

Syntax:
parseStream(stream:Readable,fileInfo?:IFileInfo|string,options?:IOptions):Promise<IAudioMetadata>
Parameters:
  • stream:Readable:

    The Node.jsReadable stream from which the audio data is read.This stream should provide the raw audio data to be analyzed.

  • fileInfo:IFileInfo (optional)

    An object containing file-related information or a string representing the MIME-type of the audio stream.The fileInfo parameter can help the parser to correctly identify the audio format and may include:

    • mimeType: A string representing theMIME-type (e.g.,audio/mpeg).

      If provided, it is assumed the streamed file content is to be the MIME-type.If not provided, the parser will attempt to determine the format based on the content of the stream.

    • size: The total size of the audio stream in bytes (useful for streams with a known length).

    • path: A string representing the file path or filename, which can also assist in determining the format.

  • options:IOptions (optional)

    An optional object containing additional parsing options.These options allow you to customize the parsing process,such as whether to calculate the duration or skip cover art extraction.

Returns
  • Promise<IAudioMetadata>:

    A promise that resolves to anIAudioMetadata object containing detailed metadata about the audio stream.This metadata includes information about the format, codec, duration, bitrate, and any embedded tags such as artist, album, or track information.

Usage Notes
  • This function is only available in Node.js environments, as it relies on theNode.js stream API.
Example:

The following example demonstrates how to use theparseStream function to read metadata from an audio stream:

import{parseStream}from'music-metadata';import{createReadStream}from'fs';(async()=>{try{// Create a readable stream from a fileconstaudioStream=createReadStream('path/to/audio/file.mp3');// Parse the metadata from the streamconstmetadata=awaitparseStream(audioStream,{mimeType:'audio/mpeg'});// Log the parsed metadataconsole.log(metadata);}catch(error){console.error('Error parsing metadata:',error.message);}})();

Cross-platform functions

These functions are designed to be cross-platform,meaning it can be used in both Node.js and web browsers.

parseWebStream function

The parseWebStream function is used to extract metadata from an audio track provided as a web-compatible ReadableStream.This function is ideal for applications running in web environments, such as browsers,where audio data is streamed over the network or read from other web-based sources.

Syntax
parseWebStream(webStream:ReadableStream<Uint8Array>,fileInfo?:IFileInfo|string,options?:IOptions):Promise<IAudioMetadata>
Parameters
  • webStream:ReadableStream<Uint8Array>

    AReadableStream that provides the audio data to be parsed.This stream should emit Uint8Array chunks, representing the raw audio data.

  • fileInfo:IFileInfo (optional)

    An object containing file-related information or a string representing the MIME-type of the audio stream.The fileInfo parameter can help the parser to correctly identify the audio format and may include:

    • mimeType: A string representing theMIME-type (e.g.,audio/mpeg).

      If provided, it is assumed the streamed file content is to be the MIME-type.If not provided, the parser will attempt to determine the format based on the content of the stream.

    • size: The total size of the audio stream in bytes (useful for streams with a known length).

    • path: A string representing the file path or filename, which can also assist in determining the format.

  • options:IOptions (optional)

    An optional object containing additional parsing options.These options allow you to customize the parsing process,such as whether to calculate the duration or skip cover art extraction.

Returns
  • Promise<IAudioMetadata>:

    A promise that resolves to anIAudioMetadata object containing detailed metadata about the audio stream.This metadata includes information about the format, codec, duration, bitrate, and any embedded tags such as artist, album, or track information.

Example

Here’s an example of how to use theparseWebStream function to extract metadata from an audio stream in a web application:

import{parseWebStream}from'music-metadata';(async()=>{try{// Assuming you have a ReadableStream of an audio fileconstresponse=awaitfetch('https://example.com/path/to/audio/file.mp3');constwebStream=response.body;// Parse the metadata from the web streamconstmetadata=awaitparseWebStream(webStream,'audio/mpeg');// Log the parsed metadataconsole.log(metadata);}catch(error){console.error('Error parsing metadata:',error.message);}})();

The example uses thefetch API to retrieve an audio file from a URL.Theresponse.body provides aReadableStream that is then passed toparseWebStream.

parseBlob function

Parses metadata from an audio file represented as aBlob.This function is suitable for use in environments that support the ReadableStreamBYOBReader, which isavailable in Node.js 20 and above.

Syntax
parseBlob(blob:Blob,options?:IOptions={}):Promise<IAudioMetadata>
Parameters
  • blob:Blob

    The Blob object containing the audio data to be parsed.This can be a file or any binary data. If the Blob is an instance of File, its name will be used as the file path in the metadata.

  • options:IOptions (optional)

    An optional configuration object that specifies parsing options.

Returns
  • Promise<IAudioMetadata>:

    A promise that resolves to the metadata of the audio file.

Example
import{parseBlob}from'music-metadata';(async()=>{constfileInput=document.querySelector('input[type="file"]');constfile=fileInput.files[0];try{constmetadata=awaitparseBlob(file);console.log(metadata);}catch(error){console.error('Error parsing metadata:',error.message);}})();

parseBuffer function

Parses metadata from an audio file where the audio data is held in aUint8Array orBuffer.This function is particularly useful when you already have audio data in memory.

Syntax
parseBuffer(buffer:Uint8Array,fileInfo?:IFileInfo|string,opts?:IOptions={}):Promise<IAudioMetadata>
Parameters
  • uint8Array:Uint8Array

    AUint8Array containing the audio data to be parsed.

  • fileInfo:IFileInfo |string (optional)

    An object containing file information such as mimeType and size.Alternatively, you can pass a MIME-type string directly.This helps the parser understand the format of the audio data.

  • options:IOptions (optional)

    An optional configuration object that specifies parsing options.

Returns
  • Promise<IAudioMetadata>:

    A promise that resolves to the metadata of the audio file.

Example
import{parseBuffer}from'music-metadata';importfsfrom'fs';(async()=>{constbuffer=fs.readFileSync('path/to/audio/file.mp3');try{constmetadata=awaitparseBuffer(buffer,{mimeType:'audio/mpeg'});console.log(metadata);}catch(error){console.error('Error parsing metadata:',error.message);}})();

parseFromTokenizer function

Parses metadata from an audio source that implements thestrtok3 ITokenizer interface.This is a low-level function that provides flexibility for advanced use cases,such as parsing metadata from streaming audio or custom data sources.

This also enables special read modules like:

Syntax
parseFromTokenizer(tokenizer:ITokenizer,options?:IOptions):Promise<IAudioMetadata>
Parameters
  • tokenizer: ITokenizer

    An instance of an ITokenizer that provides access to the audio data.The tokenizer abstracts the reading process, enabling support for various types of sources, including streams, buffers, or custom data readers.

  • options:IOptions (optional)

    An optional configuration object that specifies parsing options.

Returns
  • Promise<IAudioMetadata>:

    A promise that resolves to the metadata of the audio source, including information like the title, artist, album, and more.

Example
import{fromNodeProviderChain}from'@aws-sdk/credential-providers';import{S3Client}from'@aws-sdk/client-s3';import{makeTokenizer}from'@tokenizer/s3';import{parseFromTokenizerasmmParseFromTokenizer}from'music-metadata';// Configure the S3 clientconsts3=newS3Client({region:'eu-west-2',credentials:fromNodeProviderChain(),});// Helper function to create a tokenizer for S3 objectsasyncfunctionmakeS3TestDataTokenizer(key,options){returnawaitmakeTokenizer(s3,{Bucket:'music-metadata',Key:key,},options);}// Function to read and log metadata from an S3 objectasyncfunctionreadMetadata(){try{// Create a tokenizer for the specified S3 objectconsttokenizer=awaitmakeS3TestDataTokenizer('path/to/audio/file.mp3',{disableChunked:false});// Parse the metadata from the tokenizerconstmetadata=awaitmmParseFromTokenizer(tokenizer);// Log the retrieved metadataconsole.log(metadata);}catch(error){console.error('Error parsing metadata:',error.message);}}// Execute the metadata reading functionreadMetadata();
Additional Resources
  • strtok3 - Learn more about theITokenizer interface and how to implement it for various use cases.
  • AWS SDK for JavaScript - Documentation on using the AWS SDK to interact with S3 and other AWS services.
  • @tokenizer/s3 - Example ofITokenizer implementation.

Handling Parse Errors

music-metadata provides a robust and extensible error handling system with custom error classes that inherit from the standard JavaScriptError.All possible parsing errors are part of a union typeUnionOfParseErrors, ensuring that every error scenario is accounted for in your code.

Union of Parse Errors

All parsing errors extend from the base classParseError and are included in theUnionOfParseErrors type:

exporttypeUnionOfParseErrors=|CouldNotDetermineFileTypeError|UnsupportedFileTypeError|UnexpectedFileContentError|FieldDecodingError|InternalParserError;

Error Types

  • CouldNotDetermineFileTypeError: Raised when the file type cannot be determined.
  • UnsupportedFileTypeError: Raised when an unsupported file type is encountered.
  • UnexpectedFileContentError: Raised when the file content does not match the expected format.
  • FieldDecodingError: Raised when a specific field in the file cannot be decoded.
  • InternalParserError: Raised for internal parser errors.

Other functions

orderTags function

Utility to Converts the native tags to a dictionary index on the tag identifier

orderTags(nativeTags:ITag[]):[tagId:string]: any[]
import{parseFile,orderTags}from'music-metadata';import{inspect}from'util';(async()=>{try{constmetadata=awaitparseFile('../test/samples/MusicBrainz - Beth Hart - Sinner\'s Prayer [id3v2.3].V2.mp3');constorderedTags=orderTags(metadata.native['ID3v2.3']);console.log(inspect(orderedTags,{showHidden:false,depth:null}));}catch(error){console.error(error.message);}})();

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.

ratingToStars(rating:number):number

selectCover function

Select cover image based on image type field, otherwise the first picture in file.

exportfunctionselectCover(pictures?:IPicture[]):IPicture|null
import{parseFile,selectCover}from'music-metadata';(async()=>{const{common}=awaitparseFile(filePath);constcover=selectCover(common.picture);// pick the cover image})();

IOptions Interface

  • duration:boolean (default:false)

    If set totrue, the parser will analyze the entire media file, if necessary, to determine its duration.This option ensures accurate duration calculation but may increase processing time for large files.

  • observer:(update: MetadataEvent) => void;:

    A callback function that is invoked whenever there is an update to the common (generic) tag or format properties during parsing.This allows for real-time updates on metadata changes.

  • skipCovers:boolean (default:false)

    If set totrue, the parser will skip the extraction of embedded cover art (images) from the media file.This can be useful to avoid processing unnecessary data if cover images are not required.

  • mkvUseIndex:boolean (default:false)

    If set to true, the parser will use the SeekHead element index to skip segment/cluster elements in Matroska-based files. This is an experimental feature and can significantly impact performance. It may also result in some metadata being skipped if it is not indexed.If the SeekHead element is absent in the Matroska file, this flag has no effect.

Note

  • Theduration option is typically included in most cases, but setting it to true ensures that the entire file is parsed if necessary to get an accurate duration.
  • UsingmkvUseIndex can improve performance in Matroska files, but be aware of potential side effects, such as missing metadata due to skipped elements.

IAudioMetadata interface

If the returned promise resolves, the metadata (TypeScriptIAudioMetadata interface) contains:

  • metadata.format Audio format information
  • metadata.common Is a generic (abstract) way of reading metadata information.
  • metadata.trackInfo Is a generic (abstract) way of reading metadata information.
  • metadata.native List of native (original) tags found in the parsed audio file.

metadata.format

The questionmark? indicates the property is optional.

Audio format information. Defined in the TypeScriptIFormat interface:

  • format.container?: string Audio encoding format. e.g.: 'flac'
  • format.codec? Name of the codec (algorithm used for the audio compression)
  • format.codecProfile?: string Codec profile / settings
  • format.tagTypes?: TagType[] List of tagging formats found in parsed audio file
  • format.duration?: number Duration in seconds
  • format.bitrate?: number Number bits per second of encoded audio file
  • format.sampleRate?: number Sampling rate in Samples per second (S/s)
  • format.bitsPerSample?: number Audio bit depth
  • format.lossless?: boolean True if lossless, false for lossy encoding
  • format.numberOfChannels?: number Number of audio channels
  • format.creationTime?: Date Track creation time
  • format.modificationTime?: Date Track modification / tag update time
  • format.trackGain?: number Track gain in dB
  • format.albumGain?: number Album gain in dB

metadata.trackInfo

To support advanced containers likeMatroska orMPEG-4, which may contain multiple audio and video tracks, theexperimental-metadata.trackInfo has been added,

metadata.trackInfo is eitherundefined or has anarray oftrackInfo

trackInfo

Audio format information. Defined in the TypeScriptIFormat interface:

  • trackInfo.type?: TrackType Track type
  • trackInfo.codecName?: string Codec name
  • trackInfo.codecSettings?: string Codec settings
  • trackInfo.flagEnabled?: boolean Set if the track is usable, default:true
  • trackInfo.flagDefault?: boolean Set if that track (audio, video or subs) SHOULD be active if no language found matches the user preference.
  • trackInfo.flagLacing?: boolean Set if the trackmay contain blocks using lacing
  • trackInfo.name?: string A human-readable track name.
  • trackInfo.language?: string Specifies the language of the track
  • trackInfo.audio?: IAudioTrack, seetrackInfo.audioTrack
  • trackInfo.video?: IVideoTrack, seetrackInfo.videoTrack
trackInfo.audioTrack
  • audioTrack.samplingFrequency?: number
  • audioTrack.outputSamplingFrequency?: number
  • audioTrack.channels?: number
  • audioTrack.channelPositions?: Buffer
  • audioTrack.bitDepth?: number
trackInfo.videoTrack
  • videoTrack.flagInterlaced?: boolean
  • videoTrack.stereoMode?: number
  • videoTrack.pixelWidth?: number
  • videoTrack.pixelHeight?: number
  • videoTrack.displayWidth?: number
  • videoTrack.displayHeight?: number
  • videoTrack.displayUnit?: number
  • videoTrack.aspectRatioType?: number
  • videoTrack.colourSpace?: Buffer
  • videoTrack.gammaValue?: number

metadata.common

Common tag documentation is automatically generated.

Examples

In order to read the duration of a stream (with the exception of file streams), in some cases you should pass the size of the file in bytes.

import{parseStream}from'music-metadata';import{inspect}from'util';(async()=>{constmetadata=awaitparseStream(someReadStream,{mimeType:'audio/mpeg',size:26838},{duration:true});console.log(inspect(metadata,{showHidden:false,depth:null}));someReadStream.close();})();

Access cover art

Viametadata.common.picture you can access an array of cover art if present.Each picture has this interface:

/** * Attached picture, typically used for cover art */exportinterfaceIPicture{/**   * Image mime type   */format:string;/**   * Image data   */data:Buffer;/**   * Optional description   */description?:string;/**   * Picture type   */type?:string;}

To assignimg HTML-object you can do something like:

import{uint8ArrayToBase64}from'uint8array-extras';img.src=`data:${picture.format};base64,${uint8ArrayToBase64(picture.data)}`;

Dependencies

Dependency diagram:

graph TD;    MMN("music-metadata (Node.js entry point)")-->MMP    MMN-->FTN    MMP("music-metadata (primary entry point)")-->S(strtok3)    MMP-->TY(token-types)    MMP-->FTP    MMP-->UAE    FTN("file-type (Node.js entry point)")-->FTP    FTP("file-type (primary entry point)")-->S    S(strtok3)-->P(peek-readable)    S(strtok3)-->TO("@tokenizer/token")    TY(token-types)-->TO    TY-->IE("ieee754")    FTP-->TY    NS("node:stream")    FTN-->NS    FTP-->UAE(uint8array-extras)    style NS fill:#F88,stroke:#A44    style IE fill:#CCC,stroke:#888    style FTN fill:#FAA,stroke:#A44    style MMN fill:#FAA,stroke:#A44
Loading

Dependency list:

CommonJS backward compatibility

Using Node.js ≥ 22, which is support loading ESM module via require

constmm=require('music-metadata');

For older Node.js version < 22, you need to dynamically importmusic-metadata:

(async()=>{// Dynamically loads the ESM module in a CommonJS projectconstmm=awaitimport('music-metadata');})();

For CommonJS TypeScript projects, using a Node.js version < 22, you can useload-esm:

This method shall has replaced the embedded CJS loader function:loadMusicMetadata().

import{loadEsm}from'load-esm';(async()=>{// Dynamically loads the ESM module in a CommonJS projectconstmm=awaitloadEsm<typeofimport('music-metadata')>('music-metadata');})();

Frequently Asked Questions

How can I traverse (a long) list of files?

What is important that file parsing should be done in a sequential manner.In a plain loop, due to the asynchronous character (like most JavaScript functions), it would cause all the files to run in parallel which is will cause your application to hang in no time.There are multiple ways of achieving this:

  1. Using recursion

    import{parseFile}from'music-metadata';functionparseFiles(audioFiles){constaudioFile=audioFiles.shift();if(audioFile){returnparseFile(audioFile).then(metadata=>{// Do great things with the metadatareturnparseFiles(audioFiles);// process rest of the files AFTER we are finished})}}
  2. Use async/await

    Useasync/await

    import{parseFile}from'music-metadata';// it is required to declare the function 'async' to allow the use of awaitasyncfunctionparseFiles(audioFiles){for(constaudioFileofaudioFiles){// await will ensure the metadata parsing is completed before we move on to the next fileconstmetadata=awaitparseFile(audioFile);// Do great things with the metadata}}

Using music-metadata with TypeScript and module-resolution set to bundler.

If the TypeScript compiler optionmoduleResolutionis set to"bundler", it does not set the ECMAScript"node" condition, causing the Node specific function fail to import.

This is the case using Next.js. Seeissue #2370 how to resolve that.

Licence

This project is licensed under theMIT License. Feel free to use, modify, and distribute as needed.


[8]ページ先頭

©2009-2025 Movatter.jp