-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add title add artist
- Loading branch information
Showing
14 changed files
with
4,443 additions
and
4,185 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -121,4 +121,7 @@ dist | |
examples/* | ||
|
||
# build folder | ||
build/* | ||
build/* | ||
|
||
# example folder | ||
example/* |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
const NodeID3 = require("node-id3"); | ||
const sharp = require("sharp"); | ||
const getMP3Duration = require("get-mp3-duration"); | ||
const { parseMarkers } = require("./parseMarkers"); | ||
|
||
async function createTags({ | ||
mp3Buffer, | ||
overwrite, | ||
markersText, | ||
title, | ||
artist, | ||
cover, | ||
}) { | ||
const currentTags = await NodeID3.read(mp3Buffer); | ||
const duration = getMP3Duration(mp3Buffer); | ||
|
||
if (!overwrite && (currentTags.chapter || currentTags.tableOfContents)) { | ||
throw new Error("File already has chapter markers"); | ||
} | ||
const { chapterTag, comment, tableOfContentsElements } = parseMarkers( | ||
markersText, | ||
duration | ||
); | ||
|
||
const totalTags = { | ||
chapter: chapterTag, | ||
comment: { | ||
language: "nld", | ||
text: comment, | ||
}, | ||
unsynchronisedLyrics: { | ||
language: "nld", | ||
text: comment, | ||
}, | ||
tableOfContents: [ | ||
{ | ||
elementID: "toc1", | ||
isOrdered: true, | ||
elements: tableOfContentsElements, | ||
}, | ||
], | ||
}; | ||
|
||
if (title) { | ||
totalTags.title = title; | ||
} | ||
if (artist) { | ||
totalTags.artist = artist; | ||
} | ||
|
||
console.info(`Writing ${chapterTag.length} chapters to mp3`); | ||
|
||
if (cover) { | ||
console.info("Adding cover image"); | ||
totalTags.image = { | ||
mime: "image/png", | ||
type: { | ||
id: 3, | ||
name: "front cover", | ||
}, | ||
imageBuffer: await sharp(cover).resize(600, 600).png().toBuffer(), | ||
}; | ||
} | ||
return totalTags; | ||
} | ||
exports.createTags = createTags; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
function formatStartTime({ hours, minutes, seconds, milliseconds }) { | ||
return hours * 3600000 + minutes * 60000 + seconds * 1000 + milliseconds; | ||
} | ||
exports.formatStartTime = formatStartTime; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
function formatTime({ hours, minutes, seconds }) { | ||
const h = hours.toString().padStart(2, "0"); | ||
const m = minutes.toString().padStart(2, "0"); | ||
const s = seconds.toString().padStart(2, "0"); | ||
return `${h}:${m}:${s}`; | ||
} | ||
exports.formatTime = formatTime; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
const parse = require("csv-parse/lib/sync"); | ||
const { formatTime } = require("./formatTime"); | ||
const { formatStartTime } = require("./formatStartTime"); | ||
const { parseTime } = require("./parseTime"); | ||
|
||
function parseMarkers(inputCsv, duration) { | ||
// remove all non-ascii characters, unfortunately including emojis 😢 | ||
const cleanCsv = inputCsv.replace(/[^\x00-\x7F]/g, ""); | ||
|
||
const chapters = parse(cleanCsv, { | ||
columns: true, | ||
delimiter: "\t", | ||
skip_empty_lines: true, | ||
}); | ||
console.info(`Read ${chapters.length} chapters from csv`); | ||
|
||
if (formatStartTime(parseTime(chapters[0].Start)) > 0) { | ||
console.info("Adding intro chapter"); | ||
const intro = { | ||
Name: "Intro", | ||
Start: "0:00.000", | ||
}; | ||
chapters.unshift(intro); | ||
} | ||
|
||
const chapterTag = chapters | ||
.map((record, i) => ({ | ||
elementID: `chap${i}`, | ||
startTimeMs: formatStartTime(parseTime(record.Start)), | ||
tags: { | ||
title: record.Name, | ||
}, | ||
})) | ||
.map((record, i, records) => ({ | ||
...record, | ||
endTimeMs: | ||
i === records.length - 1 ? duration : records[i + 1].startTimeMs, | ||
})); | ||
|
||
const comment = chapters | ||
.map((record) => `${formatTime(parseTime(record.Start))}: ${record.Name}`) | ||
.join("\n"); | ||
console.info("Writing the following chapter tags:"); | ||
console.info(comment); | ||
|
||
const tableOfContentsElements = chapterTag.map(({ elementID }) => elementID); | ||
return { chapterTag, comment, tableOfContentsElements }; | ||
} | ||
exports.parseMarkers = parseMarkers; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
const timeError = new Error("Invalid time format"); | ||
function parseTime(time) { | ||
const times = time.split(":"); | ||
let hours = 0; | ||
let minutes = 0; | ||
// only minutes, seconds and milliseconds | ||
if (times.length === 2) { | ||
minutes = parseInt(times[0]); | ||
} else if (times.length === 3) { | ||
// hours, minutes, seconds and milliseconds | ||
hours = parseInt(times[0]); | ||
minutes = parseInt(times[1]); | ||
} else { | ||
throw timeError; | ||
} | ||
const [s, ms] = times[times.length - 1].split("."); | ||
const seconds = parseInt(s); | ||
const milliseconds = parseInt(ms); | ||
|
||
const result = { hours, minutes, seconds, milliseconds }; | ||
Object.values(result).forEach((value) => { | ||
if (isNaN(value)) { | ||
throw timeError; | ||
} | ||
}); | ||
|
||
return { hours, minutes, seconds, milliseconds }; | ||
} | ||
exports.parseTime = parseTime; |
Oops, something went wrong.