mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2024-12-20 19:06:06 +01:00
add new parser for overdrive media markers
This commit is contained in:
parent
5643c846ee
commit
9877b139f6
@ -3,6 +3,7 @@ const Logger = require('../../Logger')
|
||||
const BookMetadata = require('../metadata/BookMetadata')
|
||||
const { areEquivalent, copyValue } = require('../../utils/index')
|
||||
const { parseOpfMetadataXML } = require('../../utils/parsers/parseOpfMetadata')
|
||||
const { getOverdriveMediaMarkersFromFiles, parseOverdriveMediaMarkers } = require('../../utils/parsers/parseOverdriveMediaMarkers')
|
||||
const abmetadataGenerator = require('../../utils/abmetadataGenerator')
|
||||
const { readTextFile } = require('../../utils/fileUtils')
|
||||
const AudioFile = require('../files/AudioFile')
|
||||
@ -398,116 +399,17 @@ class Book {
|
||||
return wasUpdated
|
||||
}
|
||||
|
||||
generateChaptersFromOverdriveMediaMarkers(overdriveMediaMarkers, includedAudioFiles) {
|
||||
var parseString = require('xml2js').parseString; // function to convert xml to JSON
|
||||
|
||||
var parsedOverdriveMediaMarkers = [] // an array of objects. each object being a chapter with a name and time key. the values are arrays of strings
|
||||
|
||||
overdriveMediaMarkers.forEach(function (item, index) {
|
||||
var parsed_result
|
||||
parseString(item, function (err, result) {
|
||||
// result.Markers.Marker is the result of parsing the XML for the MediaMarker tags for the MP3 file (Part##.mp3)
|
||||
// it is shaped like this:
|
||||
// [
|
||||
// {
|
||||
// "Name": [
|
||||
// "Chapter 1: "
|
||||
// ],
|
||||
// "Time": [
|
||||
// "0:00.000"
|
||||
// ]
|
||||
// },
|
||||
// {
|
||||
// "Name": [
|
||||
// "Chapter 2: "
|
||||
// ],
|
||||
// "Time": [
|
||||
// "15:51.000"
|
||||
// ]
|
||||
// }
|
||||
// ]
|
||||
|
||||
parsed_result = result.Markers.Marker
|
||||
|
||||
// The values for Name and Time in parsed_results are returned as Arrays from parseString
|
||||
// update them to be strings
|
||||
parsed_result.forEach((item, index) => {
|
||||
Object.keys(item).forEach(key => {
|
||||
item[key] = item[key].toString()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
parsedOverdriveMediaMarkers.push(parsed_result)
|
||||
})
|
||||
|
||||
// go from an array of arrays of objects to an array of objects
|
||||
// end result looks like:
|
||||
// [
|
||||
// {
|
||||
// "Name": "Chapter 1: The Worst Birthday",
|
||||
// "Time": "0:00.000"
|
||||
// },
|
||||
// {
|
||||
// "Name": "Chapter 2: Dobby's Warning",
|
||||
// "Time": "15:51.000"
|
||||
// },
|
||||
// { redacted }
|
||||
// ]
|
||||
parsedOverdriveMediaMarkers = parsedOverdriveMediaMarkers
|
||||
|
||||
var index = 0
|
||||
|
||||
var time = 0.0
|
||||
|
||||
|
||||
// actually generate the chapter object
|
||||
// logic ported over from benonymity's OverdriveChapterizer:
|
||||
// https://github.com/benonymity/OverdriveChapterizer/blob/main/chapters.py
|
||||
var length = 0.0
|
||||
var newOChapters = []
|
||||
const weirdChapterFilterRegex = /([(]\d|[cC]ontinued)/
|
||||
includedAudioFiles.forEach((track, track_index) => {
|
||||
parsedOverdriveMediaMarkers[track_index].forEach((chapter) => {
|
||||
Logger.debug(`[Book] Attempting regex check for ${chapter.Name}!`)
|
||||
if (weirdChapterFilterRegex.test(chapter.Name)) {
|
||||
Logger.debug(`[Book] That shit weird yo`)
|
||||
return
|
||||
}
|
||||
time = chapter.Time.split(":")
|
||||
time = length + parseFloat(time[0]) * 60 + parseFloat(time[1])
|
||||
newOChapters.push(
|
||||
{
|
||||
id: index++,
|
||||
start: time,
|
||||
end: length,
|
||||
title: chapter.Name
|
||||
}
|
||||
)
|
||||
})
|
||||
length += track.duration
|
||||
})
|
||||
|
||||
Logger.debug(`[Book] newOChapters: ${JSON.stringify(newOChapters)}`)
|
||||
return newOChapters
|
||||
}
|
||||
|
||||
getOverdriveMediaMarkers(audioFiles) {
|
||||
var markers = audioFiles.map((af) => af.metaTags.tagOverdriveMediaMarker).filter(notUndefined => notUndefined !== undefined).filter(elem => { return elem !== null }) || []
|
||||
return markers
|
||||
}
|
||||
|
||||
setChapters(preferOverdriveMediaMarker = false) {
|
||||
// If 1 audio file without chapters, then no chapters will be set
|
||||
var includedAudioFiles = this.audioFiles.filter(af => !af.exclude)
|
||||
|
||||
var overdriveMediaMarkers = this.getOverdriveMediaMarkers(includedAudioFiles)
|
||||
var overdriveMediaMarkers = getOverdriveMediaMarkersFromFiles(includedAudioFiles)
|
||||
|
||||
// If preferOverdriveMediaMarker is set, try and use that first
|
||||
// fallback to non-overdrive chapters if there are no Overdrive Media Markers available
|
||||
if (preferOverdriveMediaMarker && (overdriveMediaMarkers.length > 0)) {
|
||||
Logger.debug(`[Book] preferring overdrive media markers! Lets generate em.`)
|
||||
this.chapters = this.generateChaptersFromOverdriveMediaMarkers(overdriveMediaMarkers, includedAudioFiles)
|
||||
this.chapters = parseOverdriveMediaMarkers(overdriveMediaMarkers, includedAudioFiles)
|
||||
} else {
|
||||
if (includedAudioFiles.length === 1) {
|
||||
// 1 audio file with chapters
|
||||
|
101
server/utils/parsers/parseOverdriveMediaMarkers.js
Normal file
101
server/utils/parsers/parseOverdriveMediaMarkers.js
Normal file
@ -0,0 +1,101 @@
|
||||
const Logger = require('../../Logger')
|
||||
|
||||
// given an array of audioFiles, return an array of unparsed MediaMarkers
|
||||
module.exports.getOverdriveMediaMarkersFromFiles = (audioFiles) => {
|
||||
var markers = audioFiles.map((af) => af.metaTags.tagOverdriveMediaMarker).filter(notUndefined => notUndefined !== undefined).filter(elem => { return elem !== null }) || []
|
||||
return markers
|
||||
}
|
||||
|
||||
module.exports.parseOverdriveMediaMarkers = (overdriveMediaMarkers, includedAudioFiles) => {
|
||||
var parseString = require('xml2js').parseString; // function to convert xml to JSON
|
||||
|
||||
var parsedOverdriveMediaMarkers = [] // an array of objects. each object being a chapter with a name and time key. the values are arrays of strings
|
||||
|
||||
overdriveMediaMarkers.forEach(function (item, index) {
|
||||
var parsed_result
|
||||
parseString(item, function (err, result) {
|
||||
// result.Markers.Marker is the result of parsing the XML for the MediaMarker tags for the MP3 file (Part##.mp3)
|
||||
// it is shaped like this:
|
||||
// [
|
||||
// {
|
||||
// "Name": [
|
||||
// "Chapter 1: "
|
||||
// ],
|
||||
// "Time": [
|
||||
// "0:00.000"
|
||||
// ]
|
||||
// },
|
||||
// {
|
||||
// "Name": [
|
||||
// "Chapter 2: "
|
||||
// ],
|
||||
// "Time": [
|
||||
// "15:51.000"
|
||||
// ]
|
||||
// }
|
||||
// ]
|
||||
|
||||
parsed_result = result.Markers.Marker
|
||||
|
||||
// The values for Name and Time in parsed_results are returned as Arrays from parseString
|
||||
// update them to be strings
|
||||
parsed_result.forEach((item, index) => {
|
||||
Object.keys(item).forEach(key => {
|
||||
item[key] = item[key].toString()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
parsedOverdriveMediaMarkers.push(parsed_result)
|
||||
})
|
||||
|
||||
// go from an array of arrays of objects to an array of objects
|
||||
// end result looks like:
|
||||
// [
|
||||
// {
|
||||
// "Name": "Chapter 1: The Worst Birthday",
|
||||
// "Time": "0:00.000"
|
||||
// },
|
||||
// {
|
||||
// "Name": "Chapter 2: Dobby's Warning",
|
||||
// "Time": "15:51.000"
|
||||
// },
|
||||
// { redacted }
|
||||
// ]
|
||||
parsedOverdriveMediaMarkers = parsedOverdriveMediaMarkers
|
||||
|
||||
var index = 0
|
||||
|
||||
var time = 0.0
|
||||
|
||||
|
||||
// actually generate the chapter object
|
||||
// logic ported over from benonymity's OverdriveChapterizer:
|
||||
// https://github.com/benonymity/OverdriveChapterizer/blob/main/chapters.py
|
||||
var length = 0.0
|
||||
var newOChapters = []
|
||||
const weirdChapterFilterRegex = /([(]\d|[cC]ontinued)/
|
||||
includedAudioFiles.forEach((track, track_index) => {
|
||||
parsedOverdriveMediaMarkers[track_index].forEach((chapter) => {
|
||||
Logger.debug(`[parseOverdriveMediaMarkers] Attempting regex check for ${chapter.Name}!`)
|
||||
if (weirdChapterFilterRegex.test(chapter.Name)) {
|
||||
Logger.debug(`[parseOverdriveMediaMarkers] That shit weird yo`)
|
||||
return
|
||||
}
|
||||
time = chapter.Time.split(":")
|
||||
time = length + parseFloat(time[0]) * 60 + parseFloat(time[1])
|
||||
newOChapters.push(
|
||||
{
|
||||
id: index++,
|
||||
start: time,
|
||||
end: length,
|
||||
title: chapter.Name
|
||||
}
|
||||
)
|
||||
})
|
||||
length += track.duration
|
||||
})
|
||||
|
||||
Logger.debug(`[parseOverdriveMediaMarkers] newOChapters: ${JSON.stringify(newOChapters)}`)
|
||||
return newOChapters
|
||||
}
|
Loading…
Reference in New Issue
Block a user