diff --git a/package.json b/package.json index 8c5cfd63..6ef5ada4 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,6 @@ "podcast": "^1.3.0", "read-chunk": "^3.1.0", "recursive-readdir-async": "^1.1.8", - "sharp": "^0.29.3", "socket.io": "^4.1.3", "string-strip-html": "^8.3.0", "watcher": "^1.2.0", diff --git a/server/CacheManager.js b/server/CacheManager.js index c31a25f9..cbe59ac9 100644 --- a/server/CacheManager.js +++ b/server/CacheManager.js @@ -1,8 +1,8 @@ const Path = require('path') const fs = require('fs-extra') const stream = require('stream') -const resize = require('./utils/resizeImage') const Logger = require('./Logger') +const { resizeImage } = require('./utils/ffmpegHelpers') class CacheManager { constructor(MetadataPath) { @@ -18,7 +18,7 @@ class CacheManager { res.type(`image/${format}`) - var path = Path.join(this.CoverCachePath, audiobook.id) + '.' + format + var path = Path.join(this.CoverCachePath, `${audiobook.id}_${width}${height ? `x${height}` : ''}`) + '.' + format // Cache exists if (await fs.pathExists(path)) { @@ -35,22 +35,22 @@ class CacheManager { // Write cache await fs.ensureDir(this.CoverCachePath) - var readStream = resize(audiobook.book.coverFullPath, width, height, format) - var writeStream = fs.createWriteStream(path) - writeStream.on('error', (e) => { - Logger.error(`[CacheManager] Cache write error ${e.message}`) - }) - readStream.pipe(writeStream) + let writtenFile = await resizeImage(audiobook.book.coverFullPath || audiobook.book.cover, path, width, height) + var readStream = fs.createReadStream(writtenFile) readStream.pipe(res) } - purgeCoverCache(audiobookId) { - var basepath = Path.join(this.CoverCachePath, audiobookId) - // Remove both webp and jpg caches if exist - var webpPath = basepath + '.webp' - var jpgPath = basepath + '.jpg' - return Promise.all([this.removeCache(webpPath), this.removeCache(jpgPath)]) + async purgeCoverCache(audiobookId) { + // If purgeAll has been called... The cover cache directory no longer exists + await fs.ensureDir(this.CoverCachePath) + return Promise.all((await fs.readdir(this.CoverCachePath)).reduce((promises, file) => { + if (file.startsWith(audiobookId)) { + Logger.debug(`[CacheManager] Going to purge ${file}`); + promises.push(this.removeCache(Path.join(this.CoverCachePath, file))) + } + return promises + }, [])) } removeCache(path) { diff --git a/server/controllers/BookController.js b/server/controllers/BookController.js index 3fa22136..b8e8cd31 100644 --- a/server/controllers/BookController.js +++ b/server/controllers/BookController.js @@ -234,7 +234,7 @@ class BookController { async getCover(req, res) { let { query: { width, height, format }, params: { id } } = req var audiobook = this.db.audiobooks.find(a => a.id === id) - if (!audiobook || !audiobook.book.coverFullPath) return res.sendStatus(404) + if (!audiobook || (!audiobook.book.coverFullPath && !audiobook.book.cover)) return res.sendStatus(404) // Check user can access this audiobooks library if (!req.user.checkCanAccessLibrary(audiobook.libraryId)) { @@ -242,7 +242,7 @@ class BookController { } const options = { - format: format || (reqSupportsWebp(req) ? 'webp' : 'jpg'), + format: format || (reqSupportsWebp(req) ? 'webp' : 'jpeg'), height: height ? parseInt(height) : null, width: width ? parseInt(width) : null } diff --git a/server/utils/ffmpegHelpers.js b/server/utils/ffmpegHelpers.js index 9ba53364..0d92685a 100644 --- a/server/utils/ffmpegHelpers.js +++ b/server/utils/ffmpegHelpers.js @@ -92,4 +92,29 @@ async function extractCoverArt(filepath, outputpath) { ffmpeg.run() }) } -module.exports.extractCoverArt = extractCoverArt \ No newline at end of file +module.exports.extractCoverArt = extractCoverArt + +//This should convert based on the output file extension as well +async function resizeImage(filePath, outputPath, width, height) { + var dirname = Path.dirname(outputPath); + await fs.ensureDir(dirname); + + return new Promise((resolve) => { + var ffmpeg = Ffmpeg(filePath) + ffmpeg.addOption(['-vf', `scale=${width || -1}:${height || -1}`]) + ffmpeg.addOutput(outputPath) + ffmpeg.on('start', (cmd) => { + Logger.debug(`[FfmpegHelpers] Resize Image Cmd: ${cmd}`) + }) + ffmpeg.on('error', (err, stdout, stderr) => { + Logger.error(`[FfmpegHelpers] Resize Image Error ${err}`) + resolve(false) + }) + ffmpeg.on('end', () => { + Logger.debug(`[FfmpegHelpers] Image resized Successfully`) + resolve(outputPath) + }) + ffmpeg.run() + }) +} +module.exports.resizeImage = resizeImage diff --git a/server/utils/resizeImage.js b/server/utils/resizeImage.js deleted file mode 100644 index aea5adff..00000000 --- a/server/utils/resizeImage.js +++ /dev/null @@ -1,16 +0,0 @@ -const sharp = require('sharp') -const fs = require('fs') - -function resize(filePath, width, height, format = 'webp') { - const readStream = fs.createReadStream(filePath); - let sharpie = sharp() - sharpie.toFormat(format) - - if (width || height) { - sharpie.resize(width, height, { withoutEnlargement: true }) - } - - return readStream.pipe(sharpie) -} - -module.exports = resize; \ No newline at end of file