Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

node-id3

Package Overview
Dependencies
Maintainers
1
Versions
38
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

node-id3 - npm Package Compare versions

Comparing version 0.2.3 to 0.2.4

10

CHANGELOG.md
# Changelog
## [0.2.3] - 2020-04-30
## [0.2.4] - 2022-11-09
- Add synchronised lyrics (SYLT frame) (by @pbricout)
## [0.2.3] - 2021-04-30
- Don't change APIC mime type on read
- Fix unsynchronisation implementation
## [0.2.2] - 2020-01-01
## [0.2.2] - 2021-01-01

@@ -205,3 +208,4 @@ ### Fixed

[unreleased]: https://github.com/Zazama/node-id3/compare/0.2.3...HEAD
[unreleased]: https://github.com/Zazama/node-id3/compare/0.2.4...HEAD
[0.2.4]: https://github.com/Zazama/node-id3/compare/0.2.3...0.2.4
[0.2.3]: https://github.com/Zazama/node-id3/compare/0.2.2...0.2.3

@@ -208,0 +212,0 @@ [0.2.2]: https://github.com/Zazama/node-id3/compare/0.2.1...0.2.2

@@ -258,3 +258,42 @@ declare module "node-id3" {

text: string
}
},
/**
* SYLT frames
*
* @see {@link https://id3.org/d3v2.3.0 4.10. Synchronised lyrics/text}
*/
synchronisedLyrics?: Array<{
/**
* 3 letter ISO 639-2 language code, for example: eng
* @see {@link https://id3.org/ISO%20639-2 ISO 639-2}
*/
language: string,
/**
* Absolute time:
* - 1: MPEG frames unit
* - 2: milliseconds unit
*/
timeStampFormat: number,
/**
* - 0: other
* - 1: lyrics
* - 2: text transcription
* - 3: movement/part name (e.g. "Adagio")
* - 4: events (e.g. "Don Quijote enters the stage")
* - 5: chord (e.g. "Bb F Fsus")
* - 6: is trivia/'pop up' information
*/
contentType: number,
/**
* Content descriptor
*/
shortText?: string,
synchronisedText: Array<{
text: string,
/**
* Absolute time in unit according to `timeStampFormat`.
*/
timeStamp: number
}>
}>,
userDefinedText?: [{

@@ -261,0 +300,0 @@ description: string,

@@ -5,2 +5,3 @@ const fs = require('fs')

const ID3Util = require('./src/ID3Util')
const zlib = require('zlib')

@@ -25,3 +26,3 @@ /*

fn(null, completeBuffer)
return
return undefined
} else {

@@ -114,3 +115,5 @@ return completeBuffer

let frames = []
if(!tags) return frames
if(!tags) {
return frames
}
const rawObject = Object.keys(tags).reduce((acc, val) => {

@@ -125,3 +128,3 @@ if(ID3Definitions.FRAME_IDENTIFIERS.v3[val] !== undefined) {

Object.keys(rawObject).forEach((specName, index) => {
Object.keys(rawObject).forEach((specName) => {
let frame

@@ -148,3 +151,3 @@ // Check if invalid specName

if (frame instanceof Buffer) {
if (frame && frame instanceof Buffer) {
frames.push(frame)

@@ -224,4 +227,6 @@ }

}
if (!(rawTags[specName] instanceof Array)) rawTags[specName] = [rawTags[specName]]
rawTags[specName].forEach((rTag, index) => {
if (!(rawTags[specName] instanceof Array)) {
rawTags[specName] = [rawTags[specName]]
}
rawTags[specName].forEach((rTag) => {
const comparison = cCompare[rTag[options.updateCompareKey]]

@@ -244,7 +249,5 @@ if (comparison !== undefined) {

return this.write(updateFn(this.read(filebuffer, options)), filebuffer)
} else {
this.read(filebuffer, (err, currentTags) => {
this.write(updateFn(this.read(filebuffer, options)), filebuffer, fn)
})
}
this.write(updateFn(this.read(filebuffer, options)), filebuffer, fn)
}

@@ -329,10 +332,40 @@

frames.forEach((frame, index) => {
frames.forEach((frame) => {
const specName = ID3Version === 2 ? ID3Definitions.FRAME_IDENTIFIERS.v3[ID3Definitions.FRAME_INTERNAL_IDENTIFIERS.v2[frame.name]] : frame.name
const identifier = ID3Version === 2 ? ID3Definitions.FRAME_INTERNAL_IDENTIFIERS.v2[frame.name] : ID3Definitions.FRAME_INTERNAL_IDENTIFIERS.v3[frame.name]
if(!specName || !identifier) {
if(!specName || !identifier || frame.flags.encryption) {
return
}
if(frame.flags.compression) {
if(frame.body.length < 5) {
return
}
const inflatedSize = frame.body.readInt32BE()
/*
* ID3 spec defines that compression is stored in ZLIB format, but doesn't specify if header is present or not.
* ZLIB has a 2-byte header.
* 1. try if header + body decompression
* 2. else try if header is not stored (assume that all content is deflated "body")
* 3. else try if inflation works if the header is omitted (implementation dependent)
* */
try {
frame.body = zlib.inflateSync(frame.body.slice(4))
} catch (e) {
try {
frame.body = zlib.inflateRawSync(frame.body.slice(4))
} catch (e) {
try {
frame.body = zlib.inflateRawSync(frame.body.slice(6))
} catch (e) {
return
}
}
}
if(frame.body.length !== inflatedSize) {
return
}
}
let decoded

@@ -350,7 +383,11 @@ if(ID3Frames[specName]) {

if(!options.onlyRaw) {
if(!tags[identifier]) tags[identifier] = []
if(!tags[identifier]) {
tags[identifier] = []
}
tags[identifier].push(decoded)
}
if(!options.noRaw) {
if(!raw[specName]) raw[specName] = []
if(!raw[specName]) {
raw[specName] = []
}
raw[specName].push(decoded)

@@ -369,4 +406,8 @@ }

if(options.onlyRaw) return raw
if(options.noRaw) return tags
if(options.onlyRaw) {
return raw
}
if(options.noRaw) {
return tags
}

@@ -385,3 +426,3 @@ tags.raw = raw

if(framePosition === -1) {
if (framePosition === -1) {
return data

@@ -397,8 +438,8 @@ }

if(data.length >= framePosition + 10) {
if (data.length >= framePosition + 10) {
const size = ID3Util.decodeSize(data.slice(framePosition + 6, framePosition + 10))
return Buffer.concat([data.slice(0, framePosition), data.slice(framePosition + size + 10)])
} else {
return data
}
return data
}

@@ -433,23 +474,23 @@

return true
} else {
fs.readFile(filepath, function(err, data) {
}
fs.readFile(filepath, function(err, data) {
if(err) {
fn(err)
}
let newData = this.removeTagsFromBuffer(data)
if(!newData) {
fn(err)
return
}
fs.writeFile(filepath, newData, 'binary', function(err) {
if(err) {
fn(err)
} else {
fn(false)
}
let newData = this.removeTagsFromBuffer(data)
if(!newData) {
fn(err)
return
}
fs.writeFile(filepath, newData, 'binary', function(err) {
if(err) {
fn(err)
} else {
fn(false)
}
})
}.bind(this))
}
})
}.bind(this))
}

@@ -461,4 +502,7 @@

this.write(tags, file, (err, ret) => {
if(err) reject(err)
else resolve(ret)
if(err) {
reject(err)
} else {
resolve(ret)
}
})

@@ -470,4 +514,7 @@ })

this.update(tags, file, (err, ret) => {
if(err) reject(err)
else resolve(ret)
if(err) {
reject(err)
} else {
resolve(ret)
}
})

@@ -486,4 +533,7 @@ })

this.read(file, options, (err, ret) => {
if(err) reject(err)
else resolve(ret)
if(err) {
reject(err)
} else {
resolve(ret)
}
})

@@ -495,4 +545,7 @@ })

this.removeTags(filepath, (err) => {
if(err) reject(err)
else resolve()
if(err) {
reject(err)
} else {
resolve()
}
})

@@ -499,0 +552,0 @@ })

{
"name": "node-id3",
"version": "0.2.3",
"version": "0.2.4",
"description": "Pure JavaScript ID3v2 Tag writer and reader",

@@ -5,0 +5,0 @@ "author": "Jan Metzger <jan.metzger@gmx.net>",

@@ -36,2 +36,4 @@ # node-id3

### 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.
```javascript

@@ -51,3 +53,4 @@ const success = NodeID3.write(tags, filepath) // Returns true/Error

### Update existing tags of file or buffer
This will write new/changed values but keep all others
The update method works like the write method but will keep or overwrite existing tags instead of removing them.
```javascript

@@ -72,2 +75,3 @@ const success = NodeID3.update(tags, filepath) // Returns true/Error

### 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.
```javascript

@@ -184,2 +188,16 @@ const success = NodeID3.create(tags) // Returns ID3-Tag Buffer

}
// See documentation for more details.
synchronisedLyrics: [{
language: "eng",
timeStampFormat: 2, // Absolute milliseconds
contentType: 1, // Lyrics
shortText: "Content descriptor",
synchronisedText: [{
text: "part 1",
timeStamp: 0
}, {
text: "part 2",
timeStamp: 1000
}]
}]
userDefinedText: [{

@@ -290,2 +308,3 @@ description: "txxx name",

unsynchronisedLyrics "USLT"
synchronisedLyrics "SYLT"
userDefinedText "TXXX"

@@ -292,0 +311,0 @@ popularimeter "POPM"

@@ -89,2 +89,3 @@ const FRAME_IDENTIFIERS = {

unsynchronisedLyrics: "USLT",
synchronisedLyrics: "SYLT",
userDefinedText: "TXXX",

@@ -144,2 +145,5 @@ popularimeter: "POPM",

},
"SYLT": {
multiple: true
},
"COMM": {

@@ -146,0 +150,0 @@ multiple: false /* change in 1.0 */

@@ -165,2 +165,45 @@ const fs = require('fs')

module.exports.SYLT = {
create: (data) => {
if(!(data instanceof Array)) {
data = [data]
}
const encoding = 1; // 16 bit unicode
return Buffer.concat(data.map(lycics => {
const frameBuilder = new ID3FrameBuilder("SYLT")
.appendStaticNumber(encoding, 1)
.appendStaticValue(lycics.language, 3)
.appendStaticNumber(lycics.timeStampFormat, 1)
.appendStaticNumber(lycics.contentType, 1)
.appendNullTerminatedValue(lycics.shortText, encoding)
lycics.synchronisedText.forEach(part => {
frameBuilder.appendNullTerminatedValue(part.text, encoding)
frameBuilder.appendStaticNumber(part.timeStamp, 4)
})
return frameBuilder.getBuffer()
}))
},
read: (buffer) => {
const reader = new ID3FrameReader(buffer, 0)
return {
language: reader.consumeStaticValue('string', 3, 0x00),
timeStampFormat: reader.consumeStaticValue('number', 1),
contentType: reader.consumeStaticValue('number', 1),
shortText: reader.consumeNullTerminatedValue('string'),
synchronisedText: Array.from((function*() {
while(true) {
const text = reader.consumeNullTerminatedValue('string')
const timeStamp = reader.consumeStaticValue('number', 4)
if (text === undefined || timeStamp === undefined) {
break
}
yield {text, timeStamp}
}
})())
}
}
}
module.exports.TXXX = {

@@ -167,0 +210,0 @@ create: (data) => {

@@ -186,2 +186,25 @@ const NodeID3 = require('../index.js')

it('create SYLT frame', function() {
let tags = {
synchronisedLyrics: [{
language: "deu",
timeStampFormat: 2, // Milliseconds
contentType: 1, // Lyrics
shortText: "Haiwsää#",
synchronisedText: [{
text: "askdh ashd olahs",
timeStamp: 0
}, {
text: "elowz dlouaish dkajh",
timeStamp: 1000
}]
}]
}
assert.strictEqual(Buffer.compare(
NodeID3.create(tags),
Buffer.from('4944330300000000007c53594c54000000720000016465750201fffe48006100690077007300e400e40023000000fffe610073006b00640068002000610073006800640020006f006c00610068007300000000000000fffe65006c006f0077007a00200064006c006f0075006100690073006800200064006b0061006a0068000000000003e8', 'hex')
), 0)
})
it('create COMM frame', function() {

@@ -474,2 +497,23 @@ const tags = {

it('read SYLT frame', function() {
let frameBuf = Buffer.from('4944330300000000007c53594c54000000720000016465750201fffe48006100690077007300e400e40023000000fffe610073006b00640068002000610073006800640020006f006c00610068007300000000000000fffe65006c006f0077007a00200064006c006f0075006100690073006800200064006b0061006a0068000000000003e8', 'hex')
const synchronisedLyrics = [{
language: "deu",
timeStampFormat: 2, // Milliseconds
contentType: 1, // Lyrics
shortText: "Haiwsää#",
synchronisedText: [{
text: "askdh ashd olahs",
timeStamp: 0
}, {
text: "elowz dlouaish dkajh",
timeStamp: 1000
}]
}]
assert.deepStrictEqual(
NodeID3.read(frameBuf).synchronisedLyrics,
synchronisedLyrics
)
})
it('read COMM frame', function() {

@@ -476,0 +520,0 @@ let frameBuf = Buffer.from('4944330300000000006E434F4D4D00000064000001646575FFFE48006100690077007300E400E40023000000FFFE610073006B00640068002000610073006800640020006F006C00610068007300200065006C006F0077007A00200064006C006F0075006100690073006800200064006B0061006A006800', 'hex')

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc