mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2025-08-04 18:24:46 +02:00
Add:FFProbe api endpoint
This commit is contained in:
parent
a0e80772cd
commit
d0bce2949e
12 changed files with 201 additions and 114 deletions
|
@ -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)
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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()
|
|
@ -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
|
||||
|
|
|
@ -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
|
Loading…
Add table
Add a link
Reference in a new issue