mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2024-12-20 19:06:06 +01:00
120 lines
4.1 KiB
JavaScript
120 lines
4.1 KiB
JavaScript
const Path = require('path')
|
|
|
|
const SocketAuthority = require('../SocketAuthority')
|
|
const Logger = require('../Logger')
|
|
|
|
const fs = require('../libs/fsExtra')
|
|
|
|
const { secondsToTimestamp } = require('../utils/index')
|
|
const toneHelpers = require('../utils/toneHelpers')
|
|
const filePerms = require('../utils/filePerms')
|
|
|
|
class AudioMetadataMangaer {
|
|
constructor(db, taskManager) {
|
|
this.db = db
|
|
this.taskManager = taskManager
|
|
}
|
|
|
|
getToneMetadataObjectForApi(libraryItem) {
|
|
return toneHelpers.getToneMetadataObject(libraryItem)
|
|
}
|
|
|
|
async updateMetadataForItem(user, libraryItem, options = {}) {
|
|
const forceEmbedChapters = !!options.forceEmbedChapters
|
|
const backupFiles = !!options.backup
|
|
|
|
const audioFiles = libraryItem.media.includedAudioFiles
|
|
|
|
const itemAudioMetadataPayload = {
|
|
userId: user.id,
|
|
libraryItemId: libraryItem.id,
|
|
startedAt: Date.now(),
|
|
audioFiles: audioFiles.map(af => ({ index: af.index, ino: af.ino, filename: af.metadata.filename }))
|
|
}
|
|
|
|
SocketAuthority.emitter('audio_metadata_started', itemAudioMetadataPayload)
|
|
|
|
// Ensure folder for backup files
|
|
const itemCacheDir = Path.join(global.MetadataPath, `cache/items/${libraryItem.id}`)
|
|
let cacheDirCreated = false
|
|
if (!await fs.pathExists(itemCacheDir)) {
|
|
await fs.mkdir(itemCacheDir)
|
|
await filePerms.setDefault(itemCacheDir, true)
|
|
cacheDirCreated = true
|
|
}
|
|
|
|
// Write chapters file
|
|
const toneJsonPath = Path.join(itemCacheDir, 'metadata.json')
|
|
|
|
try {
|
|
const chapters = (audioFiles.length == 1 || forceEmbedChapters) ? libraryItem.media.chapters : null
|
|
await toneHelpers.writeToneMetadataJsonFile(libraryItem, chapters, toneJsonPath, audioFiles.length)
|
|
} catch (error) {
|
|
Logger.error(`[AudioMetadataManager] Write metadata.json failed`, error)
|
|
|
|
itemAudioMetadataPayload.failed = true
|
|
itemAudioMetadataPayload.error = 'Failed to write metadata.json'
|
|
SocketAuthority.emitter('audio_metadata_finished', itemAudioMetadataPayload)
|
|
return
|
|
}
|
|
|
|
const results = []
|
|
for (const af of audioFiles) {
|
|
const result = await this.updateAudioFileMetadataWithTone(libraryItem.id, af, toneJsonPath, itemCacheDir, backupFiles)
|
|
results.push(result)
|
|
}
|
|
|
|
// Remove temp cache file/folder if not backing up
|
|
if (!backupFiles) {
|
|
// If cache dir was created from this then remove it
|
|
if (cacheDirCreated) {
|
|
await fs.remove(itemCacheDir)
|
|
} else {
|
|
await fs.remove(toneJsonPath)
|
|
}
|
|
}
|
|
|
|
const elapsed = Date.now() - itemAudioMetadataPayload.startedAt
|
|
Logger.debug(`[AudioMetadataManager] Elapsed ${secondsToTimestamp(elapsed / 1000, true)}`)
|
|
itemAudioMetadataPayload.results = results
|
|
itemAudioMetadataPayload.elapsed = elapsed
|
|
itemAudioMetadataPayload.finishedAt = Date.now()
|
|
SocketAuthority.emitter('audio_metadata_finished', itemAudioMetadataPayload)
|
|
}
|
|
|
|
async updateAudioFileMetadataWithTone(libraryItemId, audioFile, toneJsonPath, itemCacheDir, backupFiles) {
|
|
const resultPayload = {
|
|
libraryItemId,
|
|
index: audioFile.index,
|
|
ino: audioFile.ino,
|
|
filename: audioFile.metadata.filename
|
|
}
|
|
SocketAuthority.emitter('audiofile_metadata_started', resultPayload)
|
|
|
|
// Backup audio file
|
|
if (backupFiles) {
|
|
try {
|
|
const backupFilePath = Path.join(itemCacheDir, audioFile.metadata.filename)
|
|
await fs.copy(audioFile.metadata.path, backupFilePath)
|
|
Logger.debug(`[AudioMetadataManager] Backed up audio file at "${backupFilePath}"`)
|
|
} catch (err) {
|
|
Logger.error(`[AudioMetadataManager] Failed to backup audio file "${audioFile.metadata.path}"`, err)
|
|
}
|
|
}
|
|
|
|
const _toneMetadataObject = {
|
|
'ToneJsonFile': toneJsonPath,
|
|
'TrackNumber': audioFile.index,
|
|
}
|
|
|
|
resultPayload.success = await toneHelpers.tagAudioFile(audioFile.metadata.path, _toneMetadataObject)
|
|
if (resultPayload.success) {
|
|
Logger.info(`[AudioMetadataManager] Successfully tagged audio file "${audioFile.metadata.path}"`)
|
|
}
|
|
|
|
SocketAuthority.emitter('audiofile_metadata_finished', resultPayload)
|
|
return resultPayload
|
|
}
|
|
}
|
|
module.exports = AudioMetadataMangaer
|