Procházet zdrojové kódy

feat(server): support tiff uploading (#513)

* feat(server): suport tiff uploading

* remove unused variable

Co-authored-by: Alex <alex.tran1502@gmail.com>
Thanh Pham před 2 roky
rodič
revize
ba2cda8955

+ 1 - 1
server/apps/immich/src/config/asset-upload.config.ts

@@ -9,7 +9,7 @@ import { randomUUID } from 'crypto';
 
 export const assetUploadOption: MulterOptions = {
   fileFilter: (req: Request, file: any, cb: any) => {
-    if (file.mimetype.match(/\/(jpg|jpeg|png|gif|mp4|x-msvideo|quicktime|heic|heif|dng|x-adobe-dng|webp)$/)) {
+    if (file.mimetype.match(/\/(jpg|jpeg|png|gif|mp4|x-msvideo|quicktime|heic|heif|dng|x-adobe-dng|webp|tiff)$/)) {
       cb(null, true);
     } else {
       cb(new HttpException(`Unsupported file type ${extname(file.originalname)}`, HttpStatus.BAD_REQUEST), false);

+ 2 - 2
server/apps/microservices/src/processors/metadata-extraction.processor.ts

@@ -60,8 +60,8 @@ export class MetadataExtractionProcessor {
       newExif.make = exifData['Make'] || null;
       newExif.model = exifData['Model'] || null;
       newExif.imageName = path.parse(fileName).name || null;
-      newExif.exifImageHeight = exifData['ExifImageHeight'] || null;
-      newExif.exifImageWidth = exifData['ExifImageWidth'] || null;
+      newExif.exifImageHeight = exifData['ExifImageHeight'] || exifData['ImageHeight'] || null;
+      newExif.exifImageWidth = exifData['ExifImageWidth'] || exifData['ImageWidth'] || null;
       newExif.fileSizeInByte = fileSize || null;
       newExif.orientation = exifData['Orientation'] || null;
       newExif.dateTimeOriginal = exifData['DateTimeOriginal'] || null;

+ 41 - 62
server/apps/microservices/src/processors/thumbnail.processor.ts

@@ -51,62 +51,47 @@ export class ThumbnailGeneratorProcessor {
     const jpegThumbnailPath = resizePath + originalFilename + '.jpeg';
 
     if (asset.type == AssetType.IMAGE) {
-      sharp(asset.originalPath)
-        .resize(1440, 2560, { fit: 'inside' })
-        .jpeg()
-        .rotate()
-        .toFile(jpegThumbnailPath, async (err) => {
-          if (!err) {
-            await this.assetRepository.update({ id: asset.id }, { resizePath: jpegThumbnailPath });
-
-            // Update resize path to send to generate webp queue
-            asset.resizePath = jpegThumbnailPath;
-
-            await this.thumbnailGeneratorQueue.add(
-              generateWEBPThumbnailProcessorName,
-              { asset },
-              { jobId: randomUUID() },
-            );
-            await this.metadataExtractionQueue.add(imageTaggingProcessorName, { asset }, { jobId: randomUUID() });
-            await this.metadataExtractionQueue.add(objectDetectionProcessorName, { asset }, { jobId: randomUUID() });
-            this.wsCommunicationGateway.server
-              .to(asset.userId)
-              .emit('on_upload_success', JSON.stringify(mapAsset(asset)));
-          }
-        });
+      await sharp(asset.originalPath).resize(1440, 2560, { fit: 'inside' }).jpeg().rotate().toFile(jpegThumbnailPath);
+      await this.assetRepository.update({ id: asset.id }, { resizePath: jpegThumbnailPath });
+
+      // Update resize path to send to generate webp queue
+      asset.resizePath = jpegThumbnailPath;
+
+      await this.thumbnailGeneratorQueue.add(generateWEBPThumbnailProcessorName, { asset }, { jobId: randomUUID() });
+      await this.metadataExtractionQueue.add(imageTaggingProcessorName, { asset }, { jobId: randomUUID() });
+      await this.metadataExtractionQueue.add(objectDetectionProcessorName, { asset }, { jobId: randomUUID() });
+      this.wsCommunicationGateway.server.to(asset.userId).emit('on_upload_success', JSON.stringify(mapAsset(asset)));
     }
 
     if (asset.type == AssetType.VIDEO) {
-      ffmpeg(asset.originalPath)
-        .outputOptions(['-ss 00:00:00.000', '-frames:v 1'])
-        .output(jpegThumbnailPath)
-        .on('start', () => {
-          Logger.log('Start Generating Video Thumbnail', 'generateJPEGThumbnail');
-        })
-        .on('error', (error) => {
-          Logger.error(`Cannot Generate Video Thumbnail ${error}`, 'generateJPEGThumbnail');
-          // reject();
-        })
-        .on('end', async () => {
-          Logger.log(`Generating Video Thumbnail Success ${asset.id}`, 'generateJPEGThumbnail');
-          await this.assetRepository.update({ id: asset.id }, { resizePath: jpegThumbnailPath });
-
-          // Update resize path to send to generate webp queue
-          asset.resizePath = jpegThumbnailPath;
-
-          await this.thumbnailGeneratorQueue.add(
-            generateWEBPThumbnailProcessorName,
-            { asset },
-            { jobId: randomUUID() },
-          );
-          await this.metadataExtractionQueue.add(imageTaggingProcessorName, { asset }, { jobId: randomUUID() });
-          await this.metadataExtractionQueue.add(objectDetectionProcessorName, { asset }, { jobId: randomUUID() });
-
-          this.wsCommunicationGateway.server
-            .to(asset.userId)
-            .emit('on_upload_success', JSON.stringify(mapAsset(asset)));
-        })
-        .run();
+      await new Promise((resolve, reject) => {
+        ffmpeg(asset.originalPath)
+          .outputOptions(['-ss 00:00:00.000', '-frames:v 1'])
+          .output(jpegThumbnailPath)
+          .on('start', () => {
+            Logger.log('Start Generating Video Thumbnail', 'generateJPEGThumbnail');
+          })
+          .on('error', (error) => {
+            Logger.error(`Cannot Generate Video Thumbnail ${error}`, 'generateJPEGThumbnail');
+            reject(error);
+          })
+          .on('end', async () => {
+            Logger.log(`Generating Video Thumbnail Success ${asset.id}`, 'generateJPEGThumbnail');
+            resolve(asset);
+          })
+          .run();
+      });
+
+      await this.assetRepository.update({ id: asset.id }, { resizePath: jpegThumbnailPath });
+
+      // Update resize path to send to generate webp queue
+      asset.resizePath = jpegThumbnailPath;
+
+      await this.thumbnailGeneratorQueue.add(generateWEBPThumbnailProcessorName, { asset }, { jobId: randomUUID() });
+      await this.metadataExtractionQueue.add(imageTaggingProcessorName, { asset }, { jobId: randomUUID() });
+      await this.metadataExtractionQueue.add(objectDetectionProcessorName, { asset }, { jobId: randomUUID() });
+
+      this.wsCommunicationGateway.server.to(asset.userId).emit('on_upload_success', JSON.stringify(mapAsset(asset)));
     }
   }
 
@@ -117,16 +102,10 @@ export class ThumbnailGeneratorProcessor {
     if (!asset.resizePath) {
       return;
     }
+
     const webpPath = asset.resizePath.replace('jpeg', 'webp');
 
-    sharp(asset.resizePath)
-      .resize(250)
-      .webp()
-      .rotate()
-      .toFile(webpPath, (err) => {
-        if (!err) {
-          this.assetRepository.update({ id: asset.id }, { webpPath: webpPath });
-        }
-      });
+    await sharp(asset.resizePath).resize(250).webp().rotate().toFile(webpPath);
+    await this.assetRepository.update({ id: asset.id }, { webpPath: webpPath });
   }
 }