Add:FFProbe api endpoint

This commit is contained in:
advplyr 2023-06-25 16:16:11 -05:00
parent a0e80772cd
commit d0bce2949e
12 changed files with 201 additions and 114 deletions

View file

@ -472,7 +472,7 @@ class LibraryItemController {
getToneMetadataObject(req, res) {
if (!req.user.isAdminOrUp) {
Logger.error(`[LibraryItemController] Non-root user attempted to get tone metadata object`, req.user)
Logger.error(`[LibraryItemController] Non-admin user attempted to get tone metadata object`, req.user)
return res.sendStatus(403)
}
@ -514,20 +514,31 @@ class LibraryItemController {
})
}
async toneScan(req, res) {
if (!req.libraryItem.media.audioFiles.length) {
return res.sendStatus(404)
/**
* GET api/items/:id/ffprobe/:fileid
* FFProbe JSON result from audio file
*
* @param {express.Request} req
* @param {express.Response} res
*/
async getFFprobeData(req, res) {
if (!req.user.isAdminOrUp) {
Logger.error(`[LibraryItemController] Non-admin user attempted to get ffprobe data`, req.user)
return res.sendStatus(403)
}
if (req.libraryFile.fileType !== 'audio') {
Logger.error(`[LibraryItemController] Invalid filetype "${req.libraryFile.fileType}" for fileid "${req.params.fileid}". Expected audio file`)
return res.sendStatus(400)
}
const audioFileIndex = isNullOrNaN(req.params.index) ? 1 : Number(req.params.index)
const audioFile = req.libraryItem.media.audioFiles.find(af => af.index === audioFileIndex)
const audioFile = req.libraryItem.media.findFileWithInode(req.params.fileid)
if (!audioFile) {
Logger.error(`[LibraryItemController] toneScan: Audio file not found with index ${audioFileIndex}`)
Logger.error(`[LibraryItemController] Audio file not found with inode value ${req.params.fileid}`)
return res.sendStatus(404)
}
const toneData = await this.scanner.probeAudioFileWithTone(audioFile)
res.json(toneData)
const ffprobeData = await this.scanner.probeAudioFile(audioFile)
res.json(ffprobeData)
}
/**

View file

@ -198,6 +198,7 @@ class Book {
this.coverPath = coverPath
return true
}
removeFileWithInode(inode) {
if (this.audioFiles.some(af => af.ino === inode)) {
this.audioFiles = this.audioFiles.filter(af => af.ino !== inode)
@ -210,8 +211,13 @@ class Book {
return false
}
/**
* Get audio file or ebook file from inode
* @param {string} inode
* @returns {(AudioFile|EBookFile|null)}
*/
findFileWithInode(inode) {
var audioFile = this.audioFiles.find(af => af.ino === inode)
const audioFile = this.audioFiles.find(af => af.ino === inode)
if (audioFile) return audioFile
if (this.ebookFile && this.ebookFile.ino === inode) return this.ebookFile
return null

View file

@ -15,7 +15,6 @@ class ServerSettings {
this.scannerPreferMatchedMetadata = false
this.scannerDisableWatcher = false
this.scannerPreferOverdriveMediaMarker = false
this.scannerUseTone = false
// Metadata - choose to store inside users library item folder
this.storeCoverWithItem = false
@ -72,7 +71,6 @@ class ServerSettings {
this.scannerPreferMatchedMetadata = !!settings.scannerPreferMatchedMetadata
this.scannerDisableWatcher = !!settings.scannerDisableWatcher
this.scannerPreferOverdriveMediaMarker = !!settings.scannerPreferOverdriveMediaMarker
this.scannerUseTone = !!settings.scannerUseTone
this.storeCoverWithItem = !!settings.storeCoverWithItem
this.storeMetadataWithItem = !!settings.storeMetadataWithItem
@ -139,7 +137,6 @@ class ServerSettings {
scannerPreferMatchedMetadata: this.scannerPreferMatchedMetadata,
scannerDisableWatcher: this.scannerDisableWatcher,
scannerPreferOverdriveMediaMarker: this.scannerPreferOverdriveMediaMarker,
scannerUseTone: this.scannerUseTone,
storeCoverWithItem: this.storeCoverWithItem,
storeMetadataWithItem: this.storeMetadataWithItem,
metadataFileFormat: this.metadataFileFormat,

View file

@ -121,7 +121,7 @@ class ApiRouter {
this.router.post('/items/:id/scan', LibraryItemController.middleware.bind(this), LibraryItemController.scan.bind(this))
this.router.get('/items/:id/tone-object', LibraryItemController.middleware.bind(this), LibraryItemController.getToneMetadataObject.bind(this))
this.router.post('/items/:id/chapters', LibraryItemController.middleware.bind(this), LibraryItemController.updateMediaChapters.bind(this))
this.router.post('/items/:id/tone-scan/:index?', LibraryItemController.middleware.bind(this), LibraryItemController.toneScan.bind(this))
this.router.get('/items/:id/ffprobe/:fileid', LibraryItemController.middleware.bind(this), LibraryItemController.getFFprobeData.bind(this))
this.router.get('/items/:id/file/:fileid', LibraryItemController.middleware.bind(this), LibraryItemController.getLibraryFile.bind(this))
this.router.delete('/items/:id/file/:fileid', LibraryItemController.middleware.bind(this), LibraryItemController.deleteLibraryFile.bind(this))
this.router.get('/items/:id/file/:fileid/download', LibraryItemController.middleware.bind(this), LibraryItemController.downloadLibraryFile.bind(this))

View file

@ -59,14 +59,7 @@ class MediaFileScanner {
async scan(mediaType, libraryFile, mediaMetadataFromScan, verbose = false) {
const probeStart = Date.now()
let probeData = null
// TODO: Temp not using tone for probing until more testing can be done
// if (global.ServerSettings.scannerUseTone) {
// Logger.debug(`[MediaFileScanner] using tone to probe audio file "${libraryFile.metadata.path}"`)
// probeData = await toneProber.probe(libraryFile.metadata.path, true)
// } else {
probeData = await prober.probe(libraryFile.metadata.path, verbose)
// }
const probeData = await prober.probe(libraryFile.metadata.path, verbose)
if (probeData.error) {
Logger.error(`[MediaFileScanner] ${probeData.error} : "${libraryFile.metadata.path}"`)
@ -332,9 +325,9 @@ class MediaFileScanner {
return hasUpdated
}
probeAudioFileWithTone(audioFile) {
Logger.debug(`[MediaFileScanner] using tone to probe audio file "${audioFile.metadata.path}"`)
return toneProber.rawProbe(audioFile.metadata.path)
probeAudioFile(audioFile) {
Logger.debug(`[MediaFileScanner] Running ffprobe for audio file at "${audioFile.metadata.path}"`)
return prober.rawProbe(audioFile.metadata.path)
}
}
module.exports = new MediaFileScanner()

View file

@ -1034,8 +1034,8 @@ class Scanner {
SocketAuthority.emitter('scan_complete', libraryScan.getScanEmitData)
}
probeAudioFileWithTone(audioFile) {
return MediaFileScanner.probeAudioFileWithTone(audioFile)
probeAudioFile(audioFile) {
return MediaFileScanner.probeAudioFile(audioFile)
}
}
module.exports = Scanner

View file

@ -309,3 +309,23 @@ function probe(filepath, verbose = false) {
})
}
module.exports.probe = probe
/**
* Ffprobe for audio file path
*
* @param {string} filepath
* @returns {Object} ffprobe json output
*/
function rawProbe(filepath) {
if (process.env.FFPROBE_PATH) {
ffprobe.FFPROBE_PATH = process.env.FFPROBE_PATH
}
return ffprobe(filepath)
.catch((err) => {
return {
error: err
}
})
}
module.exports.rawProbe = rawProbe