+ // Use FFmpeg to process GIF
+ if (extension === '.gif') {
+ await processGIF(path, destination, newSize)
+ } else {
+ await jimpProcessor(path, destination, newSize, extension)
+ }
+
+ if (keepOriginal !== true) await remove(path)
+}
+
+async function generateImageFromVideoFile (options: {
+ fromPath: string
+ folder: string
+ imageName: string
+ size: { width: number, height: number }
+}) {
+ const { fromPath, folder, imageName, size } = options
+
+ const pendingImageName = 'pending-' + imageName
+ const pendingImagePath = join(folder, pendingImageName)
+
+ try {
+ await generateThumbnailFromVideo(fromPath, folder, imageName)
+
+ const destination = join(folder, imageName)
+ await processImage({ path: pendingImagePath, destination, newSize: size })
+ } catch (err) {
+ logger.error('Cannot generate image from video %s.', fromPath, { err, ...lTags() })
+
+ try {
+ await remove(pendingImagePath)
+ } catch (err) {
+ logger.debug('Cannot remove pending image path after generation error.', { err, ...lTags() })
+ }
+ }
+}
+
+async function getImageSize (path: string) {
+ const inputBuffer = await readFile(path)
+
+ const image = await jimpRead(inputBuffer)
+
+ return {
+ width: image.getWidth(),
+ height: image.getHeight()
+ }
+}
+
+// ---------------------------------------------------------------------------
+
+export {
+ generateImageFilename,
+ generateImageFromVideoFile,
+
+ processImage,
+
+ getImageSize
+}
+
+// ---------------------------------------------------------------------------
+
+async function jimpProcessor (path: string, destination: string, newSize: { width: number, height: number }, inputExt: string) {
+ let sourceImage: Jimp
+ const inputBuffer = await readFile(path)