Comparing version 0.1.1 to 0.1.3
const nodeID3 = require('../index.js') | ||
const fs = require('fs') | ||
let fileBuffer = fs.readFileSync("./example/Kevin Penkin - Tomorrow.mp3") | ||
let tags = nodeID3.read(fileBuffer) | ||
console.log("old tags:"); | ||
console.log(tags); | ||
/*let fileBuffer = fs.readFileSync("./example/Kevin Penkin - Tomorrow.mp3") | ||
console.log("new tags:"); | ||
let newTags = {title: 'sample new title'}; | ||
console.log(nodeID3.read(nodeID3.update(newTags, fileBuffer))); | ||
//tags.image is the path to the image (only png/jpeg files allowed) | ||
/*const tags = { | ||
const tags = { | ||
title: "ÄäÖöÜü", | ||
artist: "Kevin Penkin", | ||
album: "TVアニメ「メイドインアビス」オリジナルサウンドトラック", | ||
APIC: "./example/mia_cover.jpg", | ||
year: 2017, | ||
//APIC: "./example/mia_cover.jpg", | ||
//year: 2017, | ||
comment: { | ||
language: "eng", | ||
shortText: "ayy", | ||
text: "some text" | ||
}, | ||
TRCK: "27" | ||
USLT: { | ||
language: "eng", | ||
shortText: "lyrics", | ||
text: "asdashdlaksh da shjdfkljays j lgkfghjlasdl ikjfgghjluias ldzoufhljkasd fhgjllbg jkasd sghrfjsagukzlojeg jfa lkjghsf lgdjkhag jklsf gjklas lgkjfgjkl asgkhjl f jklga" | ||
} | ||
//TRCK: "27" | ||
} | ||
let success = nodeID3.write(tags, "./example/Kevin Penkin - Tomorrow.mp3"); | ||
console.log(success);*/ | ||
console.log(success); | ||
*/ | ||
fileBuffer = fs.readFileSync("./example/Kevin Penkin - Tomorrow.mp3") | ||
console.log(nodeID3.read(fileBuffer)); | ||
/* | ||
console.log("new tags:"); | ||
let newTags = {title: 'sample new title'}; | ||
console.log(nodeID3.read(nodeID3.update(newTags, fileBuffer)));*/ | ||
//tags.image is the path to the image (only png/jpeg files allowed) | ||
/* | ||
console.log(nodeID3.create(tags)) | ||
@@ -32,0 +41,0 @@ |
190
index.js
@@ -72,2 +72,7 @@ const fs = require('fs') | ||
name: "APIC" | ||
}, | ||
unsynchronisedLyrics: { | ||
create: "createUnsynchronisedLyricsFrame", | ||
read: "readUnsynchronisedLyricsFrame", | ||
name: "USLT" | ||
} | ||
@@ -492,3 +497,3 @@ } | ||
let encoded = iconv.encode(text,"utf16") | ||
let encoded = iconv.encode(text, "utf16") | ||
@@ -552,6 +557,6 @@ let buffer = new Buffer(10) | ||
if(APICFrame[0] == 0x00) { | ||
picture.description = iconv.decode(APICFrame.slice(APICFrame.indexOf(0x00, 1) + 2, APICFrame.indexOf(0x00, APICFrame.indexOf(0x00, 1) + 2)), "ISO-8859-1") || undefined; | ||
descEnd = APICFrame.indexOf(0x00, APICFrame.indexOf(0x00, 1) + 2); | ||
picture.description = iconv.decode(APICFrame.slice(APICFrame.indexOf(0x00, 1) + 2, APICFrame.indexOf(0x00, APICFrame.indexOf(0x00, 1) + 2)), "ISO-8859-1") || undefined | ||
descEnd = APICFrame.indexOf(0x00, APICFrame.indexOf(0x00, 1) + 2) | ||
} else if (APICFrame[0] == 0x01) { | ||
var desc = APICFrame.slice(APICFrame.indexOf(0x00, 1) + 2); | ||
var desc = APICFrame.slice(APICFrame.indexOf(0x00, 1) + 2) | ||
var descFound = false; | ||
@@ -561,15 +566,15 @@ | ||
if(desc[i] == 0x00 && desc[i + 1] == 0x00) { | ||
descFound = i + 1; | ||
descEnd = APICFrame.indexOf(APICFrame.indexOf(0x00, 1) + 2 + i + 1); | ||
break; | ||
descFound = i + 1 | ||
descEnd = APICFrame.indexOf(APICFrame.indexOf(0x00, 1) + 2 + i + 1) | ||
break | ||
} | ||
} | ||
if(descFound) { | ||
picture.description = iconv.decode(desc.slice(0, descFound), 'utf16') || undefined; | ||
picture.description = iconv.decode(desc.slice(0, descFound), 'utf16') || undefined | ||
} | ||
} | ||
if(descEnd) { | ||
picture.imageBuffer = APICFrame.slice(descEnd + 1); | ||
picture.imageBuffer = APICFrame.slice(descEnd + 1) | ||
} else { | ||
picture.imageBuffer = APICFrame.slice(APICFrame.indexOf(0x00, 1) + 2); | ||
picture.imageBuffer = APICFrame.slice(APICFrame.indexOf(0x00, 1) + 2) | ||
} | ||
@@ -580,2 +585,63 @@ | ||
NodeID3.prototype.getEncodingByte = function(encoding) { | ||
if(!encoding || encoding === 0x00 || encoding === "ISO-8859-1") { | ||
return 0x00 | ||
} else { | ||
return 0x01 | ||
} | ||
} | ||
NodeID3.prototype.getEncodingName = function(encoding) { | ||
if(this.getEncodingByte(encoding) === 0x00) { | ||
return "ISO-8859-1" | ||
} else { | ||
return "utf16" | ||
} | ||
} | ||
NodeID3.prototype.getTerminationCount = function(encoding) { | ||
if(encoding === 0x00) { | ||
return 1 | ||
} else { | ||
return 2 | ||
} | ||
} | ||
NodeID3.prototype.createTextEncoding = function(encoding) { | ||
let buffer = new Buffer(1) | ||
buffer[0] = this.getEncodingByte(encoding) | ||
return buffer | ||
} | ||
NodeID3.prototype.createLanguage = function(language) { | ||
if(!language) { | ||
language = "eng" | ||
} else if(language.length > 3) { | ||
language = language.substring(0, 3) | ||
} | ||
return (new Buffer(language)) | ||
} | ||
NodeID3.prototype.createContentDescriptor = function(description, encoding, terminated) { | ||
if(!description) { | ||
description = terminated ? iconv.encode("\0", this.getEncodingName(encoding)) : new Buffer(0) | ||
return description | ||
} | ||
description = iconv.encode(description, this.getEncodingName(encoding)) | ||
return terminated ? Buffer.concat([description, (new Buffer(this.getTerminationCount(encoding))).fill(0x00)]) : description | ||
} | ||
NodeID3.prototype.createText = function(text, encoding, terminated) { | ||
if(!text) { | ||
text = "" | ||
} | ||
text = iconv.encode(text, this.getEncodingName(encoding)) | ||
return terminated ? Buffer.concat([text, (new Buffer(this.getTerminationCount(encoding))).fill(0x00)]) : text | ||
} | ||
/* | ||
@@ -599,26 +665,83 @@ ** comment => object { | ||
let commentOptions = new Buffer(4) | ||
commentOptions.fill(0) | ||
commentOptions[0] = 0x01 // Encoding bit => UTF-16 | ||
let encodingBuffer = this.createTextEncoding(0x01) | ||
let languageBuffer = this.createLanguage(comment.language) | ||
let descriptorBuffer = this.createContentDescriptor(comment.shortText, 0x01, true) | ||
let textBuffer = this.createText(comment.text, 0x01, false) | ||
// Make default language eng (english) | ||
if(comment.language) { | ||
commentOptions.write(comment.language, 1) | ||
} else { | ||
commentOptions.write("eng", 1) | ||
buffer.writeUInt32BE(encodingBuffer.length + languageBuffer.length + descriptorBuffer.length + textBuffer.length, 4) | ||
return Buffer.concat([buffer, encodingBuffer, languageBuffer, descriptorBuffer, textBuffer]) | ||
} | ||
/* | ||
** frame => Buffer | ||
*/ | ||
NodeID3.prototype.readCommentFrame = function(frame) { | ||
let tags = {} | ||
if(!frame) { | ||
return tags | ||
} | ||
if(frame[0] == 0x00) { | ||
tags = { | ||
language: iconv.decode(frame, "ISO-8859-1").substring(1, 4).replace(/\0/g, ""), | ||
shortText: iconv.decode(frame, "ISO-8859-1").substring(4, frame.indexOf(0x00, 1)).replace(/\0/g, ""), | ||
text: iconv.decode(frame, "ISO-8859-1").substring(frame.indexOf(0x00, 1) + 1).replace(/\0/g, "") | ||
} | ||
} else if(frame[0] == 0x01) { | ||
let descriptorEscape = 0 | ||
while(frame[descriptorEscape] !== undefined && frame[descriptorEscape] !== 0x00 || frame[descriptorEscape + 1] !== 0x00 || frame[descriptorEscape + 2] === 0x00) { | ||
descriptorEscape++ | ||
} | ||
if(frame[descriptorEscape] === undefined) { | ||
return tags | ||
} | ||
let shortText = frame.slice(4, descriptorEscape) | ||
let text = frame.slice(descriptorEscape + 2) | ||
let commentText = new Buffer(iconv.encode(comment.text, "utf16")) | ||
tags = { | ||
language: frame.toString().substring(1, 4).replace(/\0/g, ""), | ||
shortText: iconv.decode(shortText, "utf16").replace(/\0/g, ""), | ||
text: iconv.decode(text, "utf16").replace(/\0/g, "") | ||
} | ||
} | ||
comment.shortText = comment.shortText || "" | ||
var commentShortText = iconv.encode(comment.shortText, "utf16") | ||
commentShortText = Buffer.concat([commentShortText, (comment.shortText == "") ? new Buffer(2).fill(0) : new Buffer(1).fill(0)]) | ||
buffer.writeUInt32BE(commentOptions.length + commentShortText.length + commentText.length, 4) // Size of frame | ||
return Buffer.concat([buffer, commentOptions, commentShortText, commentText]) | ||
return tags | ||
} | ||
/* | ||
** unsynchronisedLyrics => object { | ||
** language: string (3 characters), | ||
** text: string | ||
** shortText: string | ||
** } | ||
**/ | ||
NodeID3.prototype.createUnsynchronisedLyricsFrame = function(unsynchronisedLyrics) { | ||
unsynchronisedLyrics = unsynchronisedLyrics || {} | ||
if(typeof unsynchronisedLyrics === 'string' || unsynchronisedLyrics instanceof String) { | ||
unsynchronisedLyrics = { | ||
text: unsynchronisedLyrics | ||
} | ||
} | ||
if(!unsynchronisedLyrics.text) { | ||
return null | ||
} | ||
// Create frame header | ||
let buffer = new Buffer(10) | ||
buffer.fill(0) | ||
buffer.write("USLT", 0) // Write header ID | ||
let encodingBuffer = this.createTextEncoding(0x01) | ||
let languageBuffer = this.createLanguage(unsynchronisedLyrics.language) | ||
let descriptorBuffer = this.createContentDescriptor(unsynchronisedLyrics.shortText, 0x01, true) | ||
let textBuffer = this.createText(unsynchronisedLyrics.text, 0x01, false) | ||
buffer.writeUInt32BE(encodingBuffer.length + languageBuffer.length + descriptorBuffer.length + textBuffer.length, 4) | ||
return Buffer.concat([buffer, encodingBuffer, languageBuffer, descriptorBuffer, textBuffer]) | ||
} | ||
/* | ||
** frame => Buffer | ||
*/ | ||
NodeID3.prototype.readCommentFrame = function(frame) { | ||
NodeID3.prototype.readUnsynchronisedLyricsFrame = function(frame) { | ||
let tags = {} | ||
@@ -636,13 +759,14 @@ | ||
} else if(frame[0] == 0x01) { | ||
let buf16 = frame.toString('hex') | ||
let doubleEscape = parseInt(buf16.indexOf("0000") / 2) | ||
if(doubleEscape < 3) { | ||
let descriptorEscape = 0 | ||
while(frame[descriptorEscape] !== undefined && frame[descriptorEscape] !== 0x00 || frame[descriptorEscape + 1] !== 0x00 || frame[descriptorEscape + 2] === 0x00) { | ||
descriptorEscape++ | ||
} | ||
if(frame[descriptorEscape] === undefined) { | ||
return tags | ||
} | ||
let shortText = new Buffer(doubleEscape - 4 + 1) | ||
let text = new Buffer(frame.length - doubleEscape - 1) | ||
frame.copy(shortText, 0, 4, doubleEscape + 1) | ||
frame.copy(text, 0, doubleEscape + 2) | ||
let shortText = frame.slice(4, descriptorEscape) | ||
let text = frame.slice(descriptorEscape + 2) | ||
tags = { | ||
language: frame.toString().substring(1, 4), | ||
language: frame.toString().substring(1, 4).replace(/\0/g, ""), | ||
shortText: iconv.decode(shortText, "utf16").replace(/\0/g, ""), | ||
@@ -649,0 +773,0 @@ text: iconv.decode(text, "utf16").replace(/\0/g, "") |
{ | ||
"name": "node-id3", | ||
"version": "0.1.1", | ||
"version": "0.1.3", | ||
"description": "Pure JavaScript ID3 Tag writer/reader", | ||
@@ -5,0 +5,0 @@ "author": "Jan Metzger <jan.metzger@gmx.net>", |
@@ -54,5 +54,5 @@ # node-id3 | ||
let tags = NodeID3.read(file) | ||
NodeID3.read(file, function(tags) { | ||
NodeID3.read(file, function(err, tags) { | ||
/* | ||
{ | ||
tags: { | ||
title: "Tomorrow", | ||
@@ -66,3 +66,3 @@ artist: "Kevin Penkin", | ||
}, | ||
description: String, | ||
description: String, | ||
imageBuffer: Buffer | ||
@@ -133,9 +133,13 @@ }, | ||
} | ||
image: { | ||
mime: "png/jpeg"/undefined, | ||
type: { | ||
unsynchronisedLyrics: { | ||
language: "eng", | ||
text: "lyrics" | ||
} | ||
image: { | ||
mime: "png/jpeg"/undefined, | ||
type: { | ||
id: 3, | ||
name: "front cover | ||
}, //See https://en.wikipedia.org/wiki/ID3#ID3v2_embedded_image_extension | ||
description: "image description", | ||
description: "image description", | ||
imageBuffer: (file buffer) | ||
@@ -148,42 +152,43 @@ } | ||
``` | ||
album: "TALB" | ||
bpm: "TBPM" | ||
composer: "TCOM" | ||
genre: "TCON" | ||
copyright: "TCOP" | ||
date: "TDAT" | ||
playlistDelay: "TDLY" | ||
encodedBy: "TENC" | ||
textWriter: "TEXT" | ||
fileType: "TFLT" | ||
time: "TIME" | ||
contentGroup: "TIT1" | ||
title: "TIT2" | ||
subtitle: "TIT3" | ||
initialKey: "TKEY" | ||
language: "TLAN" | ||
length: "TLEN" | ||
mediaType: "TMED" | ||
originalTitle: "TOAL" | ||
originalFilename: "TOFN" | ||
originalTextwriter: "TOLY" | ||
originalArtist: "TOPE" | ||
originalYear: "TORY" | ||
fileOwner: "TOWN" | ||
artist: "TPE1" | ||
performerInfo: "TPE2" | ||
conductor: "TPE3" | ||
remixArtist: "TPE4" | ||
partOfSet: "TPOS" | ||
publisher: "TPUB" | ||
trackNumber: "TRCK" | ||
recordingDates: "TRDA" | ||
internetRadioName: "TRSN" | ||
internetRadioOwner: "TRSO" | ||
size: "TSIZ" | ||
ISRC: "TSRC" | ||
encodingTechnology: "TSSE" | ||
year: "TYER" | ||
comment: "COMM" | ||
image: "APIC" | ||
album: "TALB" | ||
bpm: "TBPM" | ||
composer: "TCOM" | ||
genre: "TCON" | ||
copyright: "TCOP" | ||
date: "TDAT" | ||
playlistDelay: "TDLY" | ||
encodedBy: "TENC" | ||
textWriter: "TEXT" | ||
fileType: "TFLT" | ||
time: "TIME" | ||
contentGroup: "TIT1" | ||
title: "TIT2" | ||
subtitle: "TIT3" | ||
initialKey: "TKEY" | ||
language: "TLAN" | ||
length: "TLEN" | ||
mediaType: "TMED" | ||
originalTitle: "TOAL" | ||
originalFilename: "TOFN" | ||
originalTextwriter: "TOLY" | ||
originalArtist: "TOPE" | ||
originalYear: "TORY" | ||
fileOwner: "TOWN" | ||
artist: "TPE1" | ||
performerInfo: "TPE2" | ||
conductor: "TPE3" | ||
remixArtist: "TPE4" | ||
partOfSet: "TPOS" | ||
publisher: "TPUB" | ||
trackNumber: "TRCK" | ||
recordingDates: "TRDA" | ||
internetRadioName: "TRSN" | ||
internetRadioOwner: "TRSO" | ||
size: "TSIZ" | ||
ISRC: "TSRC" | ||
encodingTechnology: "TSSE" | ||
year: "TYER" | ||
comment: "COMM" | ||
image: "APIC" | ||
unsynchronisedLyrics "USLT" | ||
``` |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
34066
758
190