Giter Club home page Giter Club logo

node-id3's Introduction

node-id3

GitHub package.json version Travis (.org) Codecov Code Climate maintainability npm

node-id3 is an ID3-Tag library written in JavaScript.

Installation

npm install node-id3

Usage

const NodeID3 = require('node-id3')

/* Variables found in the following usage examples */

const filebuffer = Buffer.from("Some Buffer of a (mp3) file")
const filepath = './path/to/(mp3)file'

const tags = {
    title: "Tomorrow",
    artist: "Kevin Penkin",
    album: "TVアニメ「メイドインアビス」オリジナルサウンドトラック",
    APIC: "./example/mia_cover.jpg",
    TRCK: "27"
}

Write tags to file

If you have an existing file/buffer (e.g. an mp3 file) you can use the write method to write your tags into it. It will remove existing tags and add yours.

const success = NodeID3.write(tags, filepath) // Returns true/Error
// async version
NodeID3.write(tags, file, function(err) {  })

Write tags to filebuffer

const success = NodeID3.write(tags, filebuffer) // Returns Buffer
// async version
NodeID3.write(tags, file, function(err, buffer) {  })

Update existing tags of file or buffer

The update method works like the write method but will keep or overwrite existing tags instead of removing them.

const success = NodeID3.update(tags, filepath) //  Returns true/Error
const success = NodeID3.update(tags, filebuffer) //  Returns Buffer
NodeID3.update(tags, filepath, function(err, buffer) {  })
NodeID3.update(tags, filebuffer, function(err, buffer) {  })

// Possible options
const options = {
    include: ['TALB', 'TIT2'],    // only read the specified tags (default: all)
    exclude: ['APIC']            // don't read the specified tags (default: [])
}

NodeID3.update(tags, filepath, options)
const success = NodeID3.update(tags, filebuffer, options)
NodeID3.update(tags, filepath, options, function(err, buffer) {  })
NodeID3.update(tags, filebuffer, options, function(err, buffer) {  })

Create tags as buffer

The create method will return a buffer of your ID3-Tag. You can use it to e.g. write it into a file yourself instead of using the write method.

const success = NodeID3.create(tags) // Returns ID3-Tag Buffer
// async version
NodeID3.create(tags, function(buffer) {  })

Reading ID3-Tags

const tags = NodeID3.read(file)
NodeID3.read(file, function(err, tags) {})
/*
    tags: {
        title: "Tomorrow",
        artist: "Kevin Penkin",
        image: {
          mime: "image/jpeg",
          type: {
            id: 3,
            name: "front cover"
          },
          description: String,
          imageBuffer: Buffer
        },
        raw: {
          TIT2: "Tomorrow",
          TPE1: "Kevin Penkin",
          APIC: Object (See above)
        }
      }
*/

// Possible options
const options = {
    include: ['TALB', 'TIT2'],    // only read the specified tags (default: all)
    exclude: ['APIC'],            // don't read the specified tags (default: [])
    onlyRaw: false,               // only return raw object (default: false)
    noRaw: false                  // don't generate raw object (default: false)
}
const tags = NodeID3.read(file, options)

Removing ID3-Tags from file/buffer

const success = NodeID3.removeTags(filepath)  //  returns true/Error
NodeID3.removeTags(filepath, function(err) {  })

let bufferWithoutID3Frame = NodeID3.removeTagsFromBuffer(filebuffer)  //  Returns Buffer

Using Promises (available starting with v0.2)

const NodeID3Promise = require('node-id3').Promise

NodeID3.write(tags, fileOrBuffer)
NodeID3.update(tags, fileOrBuffer)
NodeID3.create(tags)
NodeID3.read(filepath)
NodeID3.removeTags(filepath)

Supported aliases/fields

album:
bpm:
composer:
genre:
copyright:
encodingTime:
date:
playlistDelay:
originalReleaseTime:
recordingTime:
releaseTime:
taggingTime:
encodedBy:
textWriter:
fileType:
involvedPeopleList:
time:
contentGroup:
title:
subtitle:
initialKey:
language:
length:
musicianCreditsList:
mediaType:
mood:
originalTitle:
originalFilename:
originalTextwriter:
originalArtist:
originalYear:
fileOwner:
artist:
performerInfo: // (album artist)
conductor:
remixArtist:
partOfSet:
producedNotice:
publisher:
trackNumber:
recordingDates:
internetRadioName:
internetRadioOwner:
albumSortOrder:
performerSortOrder:
titleSortOrder:
size:
ISRC:
encodingTechnology:
setSubtitle:
year:
comment: {
  language: "eng",
  text: "mycomment"
}
unsynchronisedLyrics: {
  language: "eng",
  text: "lyrics"
}
// See https://id3.org/ documentation for more details.
synchronisedLyrics: [{
  language: "eng",
  timeStampFormat: TagConstants.TimeStampFormat.MILLISECONDS,
  contentType: TagConstants.SynchronisedLyrics.ContentType.LYRICS,
  shortText: "Content descriptor",
  synchronisedText: [{
    text: "part 1",
    timeStamp: 0 // Must be a positive integer value
  }, {
    text: "part 2",
    timeStamp: 1000 // Must be a positive integer value
  }]
}]
userDefinedText: [{
  description: "txxx name",
  value: "TXXX value text"
}, {
  description: "txxx name 2",
  value: "TXXX value text 2"
}] // Care, update doesn't delete non-passed array items!
image: {
  mime: "image/png",
  type: {
    id: TagConstants.AttachedPicture.PictureType.FRONT_COVER
  }, // See https://en.wikipedia.org/wiki/ID3#ID3v2_embedded_image_extension
  description: "image description",
  imageBuffer: (file buffer)
},
popularimeter: {
  email: "[email protected]",
  rating: 192,  // 1-255
  counter: 12
},
private: [{
  ownerIdentifier: "AbC",
  data: "asdoahwdiohawdaw"
}, {
  ownerIdentifier: "AbCSSS",
  data: Buffer.from([0x01, 0x02, 0x05])
}],
uniqueFileIdentifier: [{
  ownerIdentifier: "owner-id-1",
  identifier: Buffer.from("identifier-1")
}], {
  ownerIdentifier: "owner-id-2",
  identifier: Buffer.from("identifier-2")
},
chapter: [{
  elementID: "Hey!", // THIS MUST BE UNIQUE!
  startTimeMs: 5000,
  endTimeMs: 8000,
  startOffsetBytes: 123, // OPTIONAL!
  endOffsetBytes: 456,   // OPTIONAL!
  tags: {                // OPTIONAL
    title: "abcdef",
    artist: "akshdas"
  }
}],
tableOfContents: [{
  elementID: "toc1",    // THIS MUST BE UNIQUE!
  isOrdered: false,     // OPTIONAL, tells a player etc. if elements are in a specific order
  elements: ['chap1'],  // OPTIONAL but most likely needed, contains the chapter/tableOfContents elementIDs
  tags: {               // OPTIONAL
    title: "abcdef"
  }
}],
commercialUrl: ["commercialurl.com"], // array or single string
copyrightUrl: "example.com",
fileUrl: "example.com",
artistUrl: ["example.com"], // array or single string
audioSourceUrl: "example.com",
radioStationUrl: "example.com",
paymentUrl: "example.com",
publisherUrl: "example.com",
userDefinedUrl: [{
  description: "URL description"
  url: "https://example.com/"
}], // array or single object
eventTimingCodes: {
  timeStampFormat: TagConstants.TimeStampFormat.MILLISECONDS,
  keyEvents: [{
    type: TagConstants.EventTimingCodes.EventType.INTRO_START,
    timeStamp: 1000 // Must be a positive integer value
  }]
},
commercialFrame: [{
  prices: {
    'EUR': 15,
    'DKK': 17.922
  },
  validUntil: { year: 2023, month: 9, day: 1},
  contactUrl: 'https://example.com',
  receivedAs: TagConstants.CommercialFrame.ReceivedAs.OTHER,
  nameOfSeller: 'Someone',
  description: 'Something',
  sellerLogo: {
    mimeType: 'image/',
    picture: Buffer.alloc(15, 0x13)
  }
}]

Supported raw IDs

You can also use the currently supported raw tags like TALB instead of album etc.

album:                "TALB"
bpm:                  "TBPM"
composer:             "TCOM"
genre:                "TCON"
copyright:            "TCOP"
date:                 "TDAT"
encodingTime:         "TDEN"
playlistDelay:        "TDLY"
originalReleaseTime:  "TDOR"
recordingTime:        "TDRC"
releaseTime:          "TDRL"
taggingTime:          "TDTG"
encodedBy:            "TENC"
textWriter:           "TEXT"
fileType:             "TFLT"
time:                 "TIME"
involvedPeopleList:   "TIPL"
contentGroup:         "TIT1"
title:                "TIT2"
subtitle:             "TIT3"
initialKey:           "TKEY"
language:             "TLAN"
length:               "TLEN"
musicianCreditsList:  "TMCL"
mediaType:            "TMED"
mood:                 "TMOO"
originalTitle:        "TOAL"
originalFilename:     "TOFN"
originalTextwriter:   "TOLY"
originalArtist:       "TOPE"
originalYear:         "TORY"
fileOwner:            "TOWN"
artist:               "TPE1"
performerInfo:        "TPE2"    (album artist)
conductor:            "TPE3"
remixArtist:          "TPE4"
partOfSet:            "TPOS"
producedNotice:       "TPRO"
publisher:            "TPUB"
trackNumber:          "TRCK"
recordingDates:       "TRDA"
internetRadioName:    "TRSN"
internetRadioOwner:   "TRSO"
size:                 "TSIZ"
albumSortOrder:       "TSOA"
performerSortOrder:   "TSOP"
titleSortOrder:       "TSOT"
ISRC:                 "TSRC"
encodingTechnology:   "TSSE"
setSubtitle:          "TSST"
year:                 "TYER"
comment:              "COMM"
image:                "APIC"
unsynchronisedLyrics  "USLT"
synchronisedLyrics    "SYLT"
userDefinedText       "TXXX"
popularimeter         "POPM"
private               "PRIV"
uniqueFileIdentifier  "UFID"
chapter               "CHAP"
tableOfContents       "CTOC"
commercialUrl         "WCOM"
copyrightUrl          "WCOP"
fileUrl               "WOAF"
artistUrl             "WOAR"
audioSourceUrl        "WOAS"
radioStationUrl       "WORS"
paymentUrl            "WPAY"
publisherUrl          "WPUB"
userDefinedUrl        "WXXX"
eventTimingCodes      "ETCO"
commercialFrame       "COMR"

node-id3's People

Contributors

chris-shaw-2011 avatar cinnamon-bun avatar devgar avatar felicitusneko avatar floriankdrone avatar ginsu417 avatar jaminfarr avatar jin60641 avatar lazytyper avatar leetcodes avatar ortexx avatar pablobirukov avatar pbricout avatar qjd2413 avatar swadicalrag avatar tiusnonos avatar trustedtomato avatar williamvenner avatar zazama avatar zyinmd avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

node-id3's Issues

Cant find mp3 files from outside __dirname?

If I put the mp3's in a music folder in the project directory and do

var read = nodeID3.read('./music/song.mp3)
It works perfectly but lets say I put them in the music folder in the linux home directory and do

var read = nodeID3.read('~/Music/song.mp3)
It doesn't work..
I've also tried other paths like '/home/USER/Music/song.mp3 and etc, any idea on how to fix?

Update using filebuffer doesn't work

It returns false when I try to read the file again using NodeID3.read.

let tags = NodeID3.read(fileBuffer);
console.log("old tags:");
console.log(tags);
// displays tags properly
        
console.log("new tags:");
let newTags = {title: 'sample new title'};
console.log(NodeID3.read(NodeID3.update(newTags, fileBuffer)));
// displays 'false'

NodeID3.update will fail with file buffer

In the update method you accept either a file path or a file buffer as input, however this method call the write method for writing the tags which only accepts a file path as input. Calling update with a file buffer will fail because write will try to pass it to fs.writeFile.

Error when writing id3 tags to big mp3 files

Hi there!

I wrote a Node.js application that batch downloads a series of podcasts, and uses node-id3 to overwrite the mp3's tags with dates, titles, etc. The application can be found here: https://github.com/garciadelcastillo/Documentos-RNE

The module works perfect when used on small files. However, when applying this on +50Mb files, I get this error:

buffer.js:74
      throw new Error(
      ^

Error: If encoding is specified then the first argument must be a string
    at new Buffer (buffer.js:74:13)
    at NodeID3.createTextFrame (D:\Dropbox\Jose Luis\code\Documentos-RNE\node_modules\node-id3\index.js:229:25)
    at NodeID3.write (D:\Dropbox\Jose Luis\code\Documentos-RNE\node_modules\node-id3\index.js:59:30)
    at WriteStream.<anonymous> (D:\Dropbox\Jose Luis\code\Documentos-RNE\app.js:205:28)
    at emitNone (events.js:91:20)
    at WriteStream.emit (events.js:185:7)
    at finishMaybe (_stream_writable.js:515:14)
    at afterWrite (_stream_writable.js:389:3)
    at onwrite (_stream_writable.js:379:7)
    at WritableState.onwrite (_stream_writable.js:90:5)

Some googling led me to trying with older versions of Node. The error showed up with v6.9.2. The module works like a charm when downgrading to Node v.5.12.0!

I'd be happy to help or answer more questions when possible.

Thanks for a super helpful module! :)

RangeError [ERR_INVALID_OPT_VALUE]: The value "4191390185" is invalid for option "size"

buffer.js:269
    throw err;
    ^

RangeError [ERR_INVALID_OPT_VALUE]: The value "4191390185" is invalid for option "size"
    at Function.alloc (buffer.js:278:3)
    at new Buffer (buffer.js:180:19)
    at NodeID3.getTagsFromBuffer (C:\test\nodejs\node_modules\node-id3\index.js:328:31)
    at NodeID3.read (C:\test\nodejs\node_modules\node-id3\index.js:226:25)
    at NodeID3.update (C:\test\nodejs\node_modules\node-id3\index.js:269:32)

Test code:

var nodeID3 = require('node-id3');
    
let path = 'giuseppe-tomasi-di-lampedusa-der-leopard-1-4.mp3';
let tags = {
    title: 'Giuseppe Tomasi di Lampedusa: Der Leopard (1/4)',
    album: 'BR 2 | radioTexte'							
};

let success = nodeID3.update(tags, path);

giuseppe-tomasi-di-lampedusa-der-leopard-1-4.mp3

Crashes Node with Buffer Out of Bounds

Found a bug where reading certain tags can cause node-id3 to crash the whole app (even in a try catch).

internal/buffer.js:75
throw new ERR_BUFFER_OUT_OF_BOUNDS();
^

RangeError [ERR_BUFFER_OUT_OF_BOUNDS]: Attempt to access memory outside buffer bounds
at boundsError (internal/buffer.js:75:11)
at Buffer.readUInt32BE (internal/buffer.js:300:5)
at NodeID3.readPopularimeterFrame (node_modules\node-id3\index.js:1078:38)
at NodeID3. (node_modules\node-id3\index.js:465:64)
at Array.map ()
at NodeID3. (node_modules\node-id3\index.js:463:40)
at Array.forEach ()
at NodeID3.getTagsFromBuffer (node_modules\node-id3\index.js:437:12)
at NodeID3. (node_modules\node-id3\index.js:292:37)
at FSReqCallback.readFileAfterClose [as oncomplete] (internal/fs/read_file_context.js:63:3) {
code: 'ERR_BUFFER_OUT_OF_BOUNDS'
}

Even if the package failed to read the file properly, could we add some safety for the failure instead of just killing the app?

On Fedora never reads tags destroys tags when writing.

With the following file (generated with audacity version 2.1.3):
01.zip

Using the following code I can't read any tags from the file, updating the tags (commented out code) will destroy the tags in the file in both Nautilus file browser properties and Rythmbox.

// "dependencies": {
//   "glob": "^7.1.2",
//   "node-id3": "^0.1.5"
// }
//node version: v10.8.0
const NodeID3 = require('node-id3');
const glob = require("glob");

const getGlob = ()=>{
  if(!process.argv[2]){
    console.log("need to provide path to files");
    process.exit(1);
  }
  const ret = `${process.argv[2]}/*.mp3`;
  console.log("Using glob:",ret);
  return ret;
};

readTags = file =>
  new Promise(
    (resolve,reject)=>
      NodeID3.read(
        file,
        (err, tags) =>
          err?reject(err):resolve(tags)
      )
  )
;

const createTag = tags =>
  new Promise(
    (resolve,reject)=>
      NodeID3.create(
        tags,
        frame=>resolve(frame)
      )
  )
;

const updateTag = (tags,file)=>
  new Promise(
    (resolve,reject)=>
      NodeID3.update(
        tags,
        file,
        (err, buffer)=>err?reject(err):resolve(buffer)
      )
  )
;

const globPromise = (path,options)=>
  new Promise(
    (resolve,reject)=>
      glob(
        path,
        options,
        (err,files)=>
          err
            ?reject(err)
            :resolve(files))
  )
;

globPromise(getGlob(), {})
.then(
  files=>
    // updateTag(NodeID3.create(tags[0]),files[0])
    // updateTag(tags[0],files[0])
    Promise.resolve()
    .then(
        ()=>readTags(files[0])
    )
).then(
  result=>console.log("ok",result)//this logs: ok { raw: {} }
).catch(
  error=>console.log("oops:",error)
);

const tags = [
  [{
    TIT2:"some title"
  }]
]

Write method console.logging written meta tags

There's a console.log statement in index.js on line 87.

NodeID3.prototype.write = function(tags, filepath) {
    var frames = [];
    frames.push(this.createTagHeader());

    var tagNames = Object.keys(tags);
    console.log(tagNames);           // <-- its this one
    var validRawTags = Object.keys(TIF).map(function(e) {
		return TIF[e]
	})

Will remove in a pull request later :)

Accident erase entire file content

The following code will erase entire file when test on some mp3 file

var ID3v2 = require('.')

var path = '/home/jun/Desktop/Stronger.mp3'
var tags = ID3v2.read(path)
console.log(tags)
ID3v2.removeTags(path)
ID3v2.write({ title: 'Test' }, path)
var tags = ID3v2.read(path)
console.log(tags)

Check these outputs, the second time call removeTagsFromBuffer, frame position == -1

{ raw:                              
   { TIT2: 'What Doesn\'t Kill You (Stronge',                            
     TPE1: 'Kelly Clarkson',        
     TALB: 'Stronger (Deluxe Edition)',                                  
     TCOP: 'QQ音乐' },              
  title: 'What Doesn\'t Kill You (Stronge',                              
  artist: 'Kelly Clarkson',         
  album: 'Stronger (Deluxe Edition)',                                    
  copyright: 'QQ音乐' }             
frame position: 0                   
size: 1014                          
new data length: 8878759            
8878759                             
frame position: -1                  
size: 171206389                     
new data length: 0                  
{ raw: { TIT2: 'Test' }, title: 'Test' }

RangeError: "size" argument must not be larger than 2147483647

I'm getting the following error when trying to read tags from a 9.7MB MP3:

RangeError: "size" argument must not be larger than 2147483647
    at Function.Buffer.alloc (buffer.js:229:3)
    at new Buffer (buffer.js:152:19)
    at NodeID3.getTagsFromBuffer (.../node_modules/node-id3/index.js:318:31)
    at NodeID3.read (.../node_modules/node-id3/index.js:226:25)
    at Object.<anonymous> (.../index.js:40:24)
    at Module._compile (module.js:624:30)
    at Object.Module._extensions..js (module.js:635:10)
    at Module.load (module.js:545:32)
    at tryModuleLoad (module.js:508:12)
    at Function.Module._load (module.js:500:3)

Snippet:

const file = 'sample.mp3'

const buf = fs.readFileSync(file)
console.log(buf.length)
// 9673454 

try {
    let tags = NodeID3.read(file)
} catch (err) {
    console.log(err)
}

Environment:

  • OSX - 10.12.6
  • Node - 8.5.0
  • node-id3 - 0.1.3

Update:

I added console.log(bodyFrameHeader.toString('utf8', 0, 4) + ' ' + bodyFrameSize) to try to debug what was flagging the size limit; here's the output:

TPE2 29
TPOS 9
WCOP 17
WOAR 40
TLEN 4
TMED 29
TXXX 29
TXXX 31
TXXX 39
TXXX 59
TXXX 31
TXXX 37
TXXX 25
GEOB 100
TXXX 31
GEOB 110
PRIV 334456
�� 3363242937

Read-only files returns success flag

Just discovered this library and fully enjoying it!

I have issue with read-only files though: they stay unchanged as they're not meant to be, but they still returns success flag when I try to update() it.

Below is my implementation.

updateTags() {
  // generate metadata for this track
  const tags = this.getTags();
  // file path
  const file = this.path;
  // assign new data
  // *note*: returns true when the file is read-only
  const success = NodeID3.update(tags, file);

  if (success) {
    logger.info(`Updated: ${file}`);
  } else {
    logger.error(`Failed to update: ${file}`);
  }
}

Write removes Artwork

I do a simple read, make some updates to title, album, then write back to MP3 file.
But once I write, the artwork is gone.
Even when I do a read then write exact content that I read, the art work is gone after the write.
Something like below makes the artwork disappear or unusable.

const tags: any = await nodeID3.read(fullPathNew);
await nodeID3.write(tags, fullPathNew);

I use WinAmp to check the tag contents including the artwork.
Before I run above code, the artwork shows, but after running above code, the artwork does not show. Please fix this problem or share how I can preserve the artwork. Other than this issue, this is a great module!

Help, APIC from url

I am using node-ID3 for a yt playlist downloader.
I wan to try to add the thumbnail from the original video to the mp3.
Now I tried reading your code but I was having a hard time as I have never learned anything about how buffers work before.

I need to get the image from a url instead of filepath and I just can't get it working. Your code seems magical, as soon as I touch it everything dies. I tried replacing the fs.readFileSync with a http request with a buffer as response but no luck. For some reason the whole function already finished writing the tags to the file before the request is done, and I can't get it to go synchronous.

I also tried creating the buffer beforehand and then trying to write it as an image tag because looking at your code I thought that might've worked but I had no luck.

I am getting desperate and I need some help...

Read function usage in README

When NodeID3.read is used asynchronously, if the function is only give one parameter, it passes the error object, not the tags, as shown in the example.

The correct usage would be as follows (using es6 syntax):

NodeID3.read(filePath, (err, tags) => {
  if (err) throw err
  console.log(Object.keys(tags))
  console.log(tags)
})

However, if you intend the behavior to actually be as shown in the readme, then the code does not behave as expected.

Not reading all id3 tags?

When I run the script on any of my mp3 files, I only see the tags for raw, encodingTechnology, title and artist.

When I view my files in iTunes, there is info on BPM, a comment, and a genre.

Do you have any idea why these would not all be captured from the script?

TypeError: Cannot read property 'multiple' of undefined

 if(SFrames[SRawToNameMap[tag]].multiple && currentTags[tag] && rawTags[tag]) 
                                           ^

TypeError: Cannot read property 'multiple' of undefined
    at C:\test\nodejs-test\node_modules\node-id3\index.js:284:44
    at Array.map (<anonymous>)
    at NodeID3.update (C:\test\nodejs-test\node_modules\node-id3\index.js:283:30)
    at Object.<anonymous> (C:\test\nodejs-test\test_node-id3.js:12:23)

test_node-id3.js:

var nodeID3 = require('node-id3');
    
var tags = {
    title: 'title',
    album: 'album'
};

var path = "test.mp3";
console.log( "\nWriting tags: %s to file %s", JSON.stringify(tags), path );

let success = nodeID3.update(tags, path);

console.log(success ? "Ok" : "Failed");

The Genre field returns (13) and I am not getting to get the time field

Hello, @Zazama.
So, I want to get the genre field of the ID3 tag. When I set this field as a Pop genre, it returns (13).
Is it correct? How can I solve that?

I have another question... How can I get the time field of the tag? because I am trying to get it but it returns undefined and I am certain that this field is set.
Thanks.

image

Update other tags will accident remove existing image tag

let image = { image: '/home/jun/Downloads/cover.jpeg' }
let comment = {
  comment: {
    language: 'eng',
    shortText: 'short text',
    text: 'text'
  }
}
NodeID3.update(image, '/home/jun/Downloads/Blue - All Rise.mp3')
NodeID3.update(comment, '/home/jun/Downloads/Blue - All Rise.mp3')

Check this line, it will throw exception when the second update invoked.

descStart is not defined

In line 192 of index.js:

if(descStart[i] == 0x00 && descStart[i + 1] == 0x00) {
        descFound = i + 1;
        descEnd = APICFrame.indexOf(APICFrame.indexOf(0x00, 1) + 2 + i + 1);
   	break;
}

descStart is not defined anywhere, so it throws an error.

Associated PR: #11

How do I use?

Hi there,

How do I use the script? I mean, what do i need to install, etc in order for this to work?
Do I just drag some js file and voila? Do I have to install something (ex. node js) and run a server based on that for it to work?

Thanks a bunch. I'm trying to learn :)

Add support for the TXXX frame (user defind text information)

Some music players such as foobar2000 can store metadata in the TXXX frame. The frame might contain statistics such as the timestamps for when the track was first played, etc. There may be multiple TXXX frames in a file, but the descriptions are unique.

The frame body is arranged a bit differently from ordinary text frames, like so:

<Header for 'User defined text information frame', ID: "TXXX">
Text encoding    $xx
Description    <text string according to encoding> $00 (00)
Value    <text string according to encoding>

Here's an example of the TXXX frame in a file:

00000000  49 44 33 03 00 00 00 06  6b 15 54 49 54 32 00 00  |ID3.....k.TIT2..|
00000010  00 25 00 00 01 ff fe 44  00 65 00 6d 00 6f 00 6c  |.%.....D.e.m.o.l|
00000020  00 69 00 74 00 69 00 6f  00 6e 00 20 00 53 00 71  |.i.t.i.o.n. .S.q|
00000030  00 75 00 61 00 64 00 00  00 54 50 45 31 00 00 00  |.u.a.d...TPE1...|
00000040  1b 00 00 01 ff fe 48 00  61 00 72 00 72 00 79 00  |......H.a.r.r.y.|
00000050  20 00 4a 00 75 00 64 00  64 00 61 00 00 00 54 58  | .J.u.d.d.a...TX| <--
00000060  58 58 00 00 00 39 00 00  01 ff fe 41 00 44 00 44  |XX...9.....A.D.D|
00000070  00 45 00 44 00 00 00 ff  fe 32 00 30 00 31 00 37  |.E.D.....2.0.1.7|
00000080  00 2d 00 30 00 37 00 2d  00 32 00 39 00 20 00 31  |.-.0.7.-.2.9. .1|
00000090  00 36 00 3a 00 32 00 31  00 3a 00 30 00 30 00 00  |.6.:.2.1.:.0.0..|
000000a0  00 54 43 4f 4e 00 00 00  0d 00 00 01 ff fe 48 00  |.TCON.........H.|
000000b0  6f 00 75 00 73 00 65 00  41 50 49 43 00 01 ac 75  |o.u.s.e.APIC...u|

Add a custom tag

I can't add a custom tag.
For example

let metadata = {
	USLT: "test",
	TRCK: "3"
};
nodeID3.write(metadata, "test");

It adds the track number but not unsynced lyrics.

improving performance of read

Hi,
I'm wondering if there is a way to improve performance of reading the meta. I don't know if the file is entirely loaded or just the meta portion, I'm passing the path to NodeID3.read(). It seems slow considering the volume I'm reading. Greetings

Support WAV format

WAV RIFF audio also uses ID3v2 comment specification,
Can you support the reading and writing of metadata in this audio format?
Thank you!

nodeID3.read() destroys Umlauts by cutting high bit off

Hi!

nodeID3.read() returns tag values with high bit on, like German umlauts, with high bit off. Thus the tag contents is destroyed.

äöüßÄÖÜ
is returned as
dv|_DV\\
or in hex:
a4 b6 bc 9f 84 96 9c
becomes
64 76 7c 5f 44 56 5c 5c

I'd rather expect that there is no conversion involved.

Is there a stream API

I want to use this library on the express server. Is there an option to add tag only in response stream?

m4a/aac file support

Probably you're not developing this anymore but in my opinion this is the best node id3 parser/writer. Whatever, I noticed that when i try to write id3 tags to a m4a file, it breaks the file and doesn't write tags.
I converted one of the m4a files to mp3 with ffmpeg and run with same code and it worked.
I guess the problem is with m4a files. Can you add support for aac/m4a please?

What is the difference between update() and write()?

I have a data like this that I am using to call update() and write().

const newMp3Tags: any = {
	title: "myTitle",
	artist: "myArtist",
	album: "myAlbum"
};

Calling update() and write() seems to have exact same behavior.

I would have thought that write() will remove all other tag data and just keep my data as tag data.
And update() would just update the tags that I have in my data and keep all others as is.
But whether or not I call update() or write(), I see all other data as if update() was called.

Japanese characters

When trying to save the following names on the Artist tag of a file, broken characters appear.
Strings I'm trying to save:

分島花音
ナノ

Both get converted to, respectively:

�ö±ó
ÊÎ

When trying to save the following string to the Title tag, same thing happens:

Dark Night Rhapsody~明けない夜の狂詩曲

This is being saved as:

Dark Night Rhapsody^�QjD�nÂiò

Any ideas?

Add support for promises

Currently the module is using callbacks, but I wanted it to use promises as I'm writing my app with ES6.

I wrote a little test like that :

import id3 from 'node-id3';
import {promisify} from 'util';

const file1 = '../img.mp3';
const file2 = '../noimg.mp3';

export function readID3(file) {
    return promisify(id3.read)(file);
}


async function main() {    
    try {
        const tags1 = await readID3(file1);
        const tags2 = await readID3(file2);
        console.log(tags1);
        console.log(tags2);
    } catch (err) {
        console.log(err);
    }
}

main().then(() => {
    process.exit();    
});

However, this fails with :

D:\perso\toyundamugen-app\node_modules\node-id3\index.js:234
                    let tags = this.getTagsFromBuffer(data, options)
                                    ^

TypeError: this.getTagsFromBuffer is not a function
    at D:\perso\toyundamugen-app\node_modules\node-id3\index.js:234:37
    at FSReqWrap.readFileAfterClose [as oncomplete] (fs.js:504:3)

I had a friend look into it and he had to create its own promisify function. This allows to promisify your module :

export function readID3(fileBuffer, options) {
  return new Promise(
      (resolve, reject) =>
          id3.read(
                fileBuffer,
              options,
              (err, tags) => {
                  if (err) {
                      reject(err);
                  } else {
                      resolve(tags);
                  }
              }
          )
  )
}

However this is not really satisfying. The best thing IMHO would be that node-id3 natively supports promises.

This is due to a binding problem with this.

I'd be grateful if you could look into this.

image.imageBuffer outputs corrupted data

Hey guys im trying to create a webservice w/ nodejs and express. Basically i just want to respond the corresponding albumart for a specific file:

//... (in a express method)
var meta = NodeID3.read(path);
if(meta.image){
  res.set('Content-Type', 'image/' + meta.image.mime);
  res.send(meta.image.imageBuffer);
}
//...

I tried it on several mp3 files - all without success.
Postman shows just this "empty" image
postman1
And the corresponding header infos
postman2
I even exported the file onto my local fs with fs.writeFileSync("test.png", meta.image.imageBuffer, 'binary');.
This is whats returned:
test
Before i forget, this album cover should look like this:
playback

Add more tags

Can you please add Synced lyrics (SYLT), upc/ean (BARCODE/UPC/EAN) and duration(Maybe there is duration already)?

How do I use the script?

Hello!

I'm trying to use the code for my website to get audio files name, singer lyrics and album art.

which file do I take into my code? (<script src="**that file**"></script)
and just to be sure -- do I read the raw tags in order to display the information?

Thanks a lot.

Add update / upsert tags method

I'm dealing with images and had to write my own wrapper functions to deal with updating single tag in a file. More hassle when I have to deal with images. Would be nice to have update / upsert feature as part of this module.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.