diff --git a/client/components/tables/TracksTable.vue b/client/components/tables/TracksTable.vue index d0f93ff4..0b25720c 100644 --- a/client/components/tables/TracksTable.vue +++ b/client/components/tables/TracksTable.vue @@ -24,6 +24,14 @@ Size Duration Download + +
+

Tone

+ + information + +
+ @@ -65,7 +76,8 @@ export default { data() { return { showTracks: false, - showFullPath: false + showFullPath: false, + toneProbing: false } }, computed: { @@ -77,11 +89,35 @@ export default { }, userCanUpdate() { return this.$store.getters['user/getUserCanUpdate'] + }, + showExperimentalFeatures() { + return this.$store.state.showExperimentalFeatures } }, methods: { clickBar() { this.showTracks = !this.showTracks + }, + toneProbe(index) { + this.toneProbing = true + + this.$axios + .$post(`/api/items/${this.libraryItemId}/tone-scan/${index}`) + .then((data) => { + console.log('Tone probe data', data) + if (data.error) { + this.$toast.error('Tone probe error: ' + data.error) + } else { + this.$toast.success('Tone probe successful! Check browser console') + } + }) + .catch((error) => { + console.error('Failed to tone probe', error) + this.$toast.error('Tone probe failed') + }) + .finally(() => { + this.toneProbing = false + }) } }, mounted() {} diff --git a/server/controllers/LibraryItemController.js b/server/controllers/LibraryItemController.js index bcaa3b33..b1f3f77d 100644 --- a/server/controllers/LibraryItemController.js +++ b/server/controllers/LibraryItemController.js @@ -1,5 +1,5 @@ const Logger = require('../Logger') -const { reqSupportsWebp } = require('../utils/index') +const { reqSupportsWebp, isNullOrNaN } = require('../utils/index') const { ScanResult } = require('../utils/constants') class LibraryItemController { @@ -464,6 +464,22 @@ class LibraryItemController { res.sendStatus(200) } + async toneScan(req, res) { + if (!req.libraryItem.media.audioFiles.length) { + return res.sendStatus(404) + } + + const audioFileIndex = isNullOrNaN(req.params.index) ? 1 : Number(req.params.index) + const audioFile = req.libraryItem.media.audioFiles.find(af => af.index === audioFileIndex) + if (!audioFile) { + Logger.error(`[LibraryItemController] toneScan: Audio file not found with index ${audioFileIndex}`) + return res.sendStatus(404) + } + + const toneData = await this.scanner.probeAudioFileWithTone(audioFile) + res.json(toneData) + } + middleware(req, res, next) { var item = this.db.libraryItems.find(li => li.id === req.params.id) if (!item || !item.media) return res.sendStatus(404) diff --git a/server/routers/ApiRouter.js b/server/routers/ApiRouter.js index e45adc4c..03fc9149 100644 --- a/server/routers/ApiRouter.js +++ b/server/routers/ApiRouter.js @@ -101,6 +101,7 @@ class ApiRouter { this.router.post('/items/:id/chapters', LibraryItemController.middleware.bind(this), LibraryItemController.updateMediaChapters.bind(this)) this.router.post('/items/:id/open-feed', LibraryItemController.middleware.bind(this), LibraryItemController.openRSSFeed.bind(this)) this.router.post('/items/:id/close-feed', LibraryItemController.middleware.bind(this), LibraryItemController.closeRSSFeed.bind(this)) + this.router.post('/items/:id/tone-scan/:index?', LibraryItemController.middleware.bind(this), LibraryItemController.toneScan.bind(this)) this.router.post('/items/batch/delete', LibraryItemController.batchDelete.bind(this)) this.router.post('/items/batch/update', LibraryItemController.batchUpdate.bind(this)) diff --git a/server/scanner/MediaFileScanner.js b/server/scanner/MediaFileScanner.js index c57d30b2..fb22cb25 100644 --- a/server/scanner/MediaFileScanner.js +++ b/server/scanner/MediaFileScanner.js @@ -289,5 +289,10 @@ class MediaFileScanner { return hasUpdated } + + probeAudioFileWithTone(audioFile) { + Logger.debug(`[MediaFileScanner] using tone to probe audio file "${audioFile.metadata.path}"`) + return toneProber.rawProbe(audioFile.metadata.path) + } } module.exports = new MediaFileScanner() \ No newline at end of file diff --git a/server/scanner/Scanner.js b/server/scanner/Scanner.js index e0604123..2caf9e0e 100644 --- a/server/scanner/Scanner.js +++ b/server/scanner/Scanner.js @@ -991,5 +991,9 @@ class Scanner { this.librariesScanning = this.librariesScanning.filter(ls => ls.id !== library.id) this.emitter('scan_complete', libraryScan.getScanEmitData) } + + probeAudioFileWithTone(audioFile) { + return MediaFileScanner.probeAudioFileWithTone(audioFile) + } } module.exports = Scanner \ No newline at end of file diff --git a/server/utils/toneProber.js b/server/utils/toneProber.js index 44dee28b..c1d8de9d 100644 --- a/server/utils/toneProber.js +++ b/server/utils/toneProber.js @@ -155,4 +155,19 @@ module.exports.probe = (filepath, verbose = false) => { error } }) +} + +module.exports.rawProbe = (filepath) => { + if (process.env.TONE_PATH) { + tone.TONE_PATH = process.env.TONE_PATH + } + + return tone.dump(filepath).then((dumpPayload) => { + return dumpPayload + }).catch((error) => { + Logger.error(`[toneProber] Failed to probe file at path "${filepath}"`, error) + return { + error + } + }) } \ No newline at end of file