Browse Source

setup image resize processor

Alex Tran 3 years ago
parent
commit
168676075f

+ 1 - 1
Makefile

@@ -1,5 +1,5 @@
 dev:
 	docker-compose -f ./server/docker-compose.yml up
 
-update:
+dev-update:
 	docker-compose -f ./server/docker-compose.yml up --build -V

+ 2 - 2
mobile/lib/shared/providers/backup.provider.dart

@@ -35,7 +35,7 @@ class BackupNotifier extends StateNotifier<BackUpState> {
   void getBackupInfo() async {
     _updateServerInfo();
 
-    List<AssetPathEntity> list = await PhotoManager.getAssetPathList(onlyAll: true, type: RequestType.image);
+    List<AssetPathEntity> list = await PhotoManager.getAssetPathList(onlyAll: true, type: RequestType.common);
 
     if (list.isEmpty) {
       debugPrint("No Asset On Device");
@@ -59,7 +59,7 @@ class BackupNotifier extends StateNotifier<BackUpState> {
       // await PhotoManager.presentLimited();
       // Gather assets info
       List<AssetPathEntity> list =
-          await PhotoManager.getAssetPathList(hasAll: true, onlyAll: true, type: RequestType.image);
+          await PhotoManager.getAssetPathList(hasAll: true, onlyAll: true, type: RequestType.common);
 
       if (list.isEmpty) {
         debugPrint("No Asset On Device - Abort Backup Process");

+ 0 - 1
mobile/lib/shared/services/backup.service.dart

@@ -12,7 +12,6 @@ import 'package:immich_mobile/utils/files_helper.dart';
 import 'package:photo_manager/photo_manager.dart';
 import 'package:http_parser/http_parser.dart';
 import 'package:path/path.dart' as p;
-import 'package:exif/exif.dart';
 
 class BackupService {
   final NetworkService _networkService = NetworkService();

+ 7 - 3
server/src/api-v1/asset/asset.controller.ts

@@ -22,7 +22,7 @@ import { AuthUserDto, GetAuthUser } from '../../decorators/auth-user.decorator';
 import { CreateAssetDto } from './dto/create-asset.dto';
 import { createReadStream } from 'fs';
 import { ServeFileDto } from './dto/serve-file.dto';
-import { ImageOptimizeService } from '../../modules/image-optimize/image-optimize.service';
+import { AssetOptimizeService } from '../../modules/image-optimize/image-optimize.service';
 import { AssetType } from './entities/asset.entity';
 import { GetAllAssetQueryDto } from './dto/get-all-asset-query.dto';
 
@@ -31,7 +31,7 @@ import { GetAllAssetQueryDto } from './dto/get-all-asset-query.dto';
 export class AssetController {
   constructor(
     private readonly assetService: AssetService,
-    private readonly imageOptimizeService: ImageOptimizeService,
+    private readonly assetOptimizeService: AssetOptimizeService,
   ) {}
 
   @Post('upload')
@@ -45,7 +45,11 @@ export class AssetController {
       const savedAsset = await this.assetService.createUserAsset(authUser, assetInfo, file.path, file.mimetype);
 
       if (savedAsset && savedAsset.type == AssetType.IMAGE) {
-        await this.imageOptimizeService.resizeImage(savedAsset);
+        await this.assetOptimizeService.resizeImage(savedAsset);
+      }
+
+      if (savedAsset && savedAsset.type == AssetType.IMAGE) {
+        await this.assetOptimizeService.resizeVideo(savedAsset);
       }
     });
 

+ 3 - 3
server/src/api-v1/asset/asset.module.ts

@@ -4,13 +4,13 @@ import { AssetController } from './asset.controller';
 import { TypeOrmModule } from '@nestjs/typeorm';
 import { AssetEntity } from './entities/asset.entity';
 import { ImageOptimizeModule } from '../../modules/image-optimize/image-optimize.module';
-import { ImageOptimizeService } from '../../modules/image-optimize/image-optimize.service';
+import { AssetOptimizeService } from '../../modules/image-optimize/image-optimize.service';
 import { BullModule } from '@nestjs/bull';
 
 @Module({
   imports: [
     BullModule.registerQueue({
-      name: 'image',
+      name: 'optimize',
       defaultJobOptions: {
         attempts: 3,
         removeOnComplete: true,
@@ -29,7 +29,7 @@ import { BullModule } from '@nestjs/bull';
     ImageOptimizeModule,
   ],
   controllers: [AssetController],
-  providers: [AssetService, ImageOptimizeService],
+  providers: [AssetService, AssetOptimizeService],
   exports: [],
 })
 export class AssetModule {}

+ 4 - 4
server/src/modules/image-optimize/image-optimize.module.ts

@@ -6,13 +6,13 @@ import { AssetModule } from '../../api-v1/asset/asset.module';
 import { AssetService } from '../../api-v1/asset/asset.service';
 import { AssetEntity } from '../../api-v1/asset/entities/asset.entity';
 import { ImageOptimizeProcessor } from './image-optimize.processor';
-import { ImageOptimizeService } from './image-optimize.service';
+import { AssetOptimizeService } from './image-optimize.service';
 import { MachineLearningProcessor } from './machine-learning.processor';
 
 @Module({
   imports: [
     BullModule.registerQueue({
-      name: 'image',
+      name: 'optimize',
       defaultJobOptions: {
         attempts: 3,
         removeOnComplete: true,
@@ -30,7 +30,7 @@ import { MachineLearningProcessor } from './machine-learning.processor';
 
     TypeOrmModule.forFeature([AssetEntity]),
   ],
-  providers: [ImageOptimizeService, ImageOptimizeProcessor, MachineLearningProcessor],
-  exports: [ImageOptimizeService],
+  providers: [AssetOptimizeService, ImageOptimizeProcessor, MachineLearningProcessor],
+  exports: [AssetOptimizeService],
 })
 export class ImageOptimizeModule {}

+ 45 - 3
server/src/modules/image-optimize/image-optimize.processor.ts

@@ -8,7 +8,7 @@ import fs, { existsSync, mkdirSync } from 'fs';
 import { ConfigService } from '@nestjs/config';
 import { randomUUID } from 'crypto';
 
-@Processor('image')
+@Processor('optimize')
 export class ImageOptimizeProcessor {
   constructor(
     @InjectRepository(AssetEntity) private assetRepository: Repository<AssetEntity>,
@@ -16,8 +16,8 @@ export class ImageOptimizeProcessor {
     private configService: ConfigService,
   ) {}
 
-  @Process('optimize')
-  async handleOptimization(job: Job) {
+  @Process('resize-image')
+  async resizeUploadedImage(job: Job) {
     const { savedAsset }: { savedAsset: AssetEntity } = job.data;
 
     const basePath = this.configService.get('UPLOAD_LOCATION');
@@ -58,4 +58,46 @@ export class ImageOptimizeProcessor {
 
     return 'ok';
   }
+
+  @Process('resize-video')
+  async resizeUploadedVideo(job: Job) {
+    const { savedAsset }: { savedAsset: AssetEntity } = job.data;
+
+    const basePath = this.configService.get('UPLOAD_LOCATION');
+    const resizePath = savedAsset.originalPath.replace('/original/', '/thumb/');
+
+    // Create folder for thumb image if not exist
+    const resizeDir = `${basePath}/${savedAsset.userId}/thumb/${savedAsset.deviceId}`;
+
+    if (!existsSync(resizeDir)) {
+      mkdirSync(resizeDir, { recursive: true });
+    }
+
+    fs.readFile(savedAsset.originalPath, (err, data) => {
+      if (err) {
+        console.error('Error Reading File');
+      }
+
+      sharp(data)
+        .resize(512, 512, { fit: 'outside' })
+        .toFile(resizePath, async (err, info) => {
+          if (err) {
+            console.error('Error resizing file ', err);
+          }
+
+          await this.assetRepository.update(savedAsset, { resizePath: resizePath });
+
+          // Send file to object detection after resizing
+          // const detectionJob = await this.machineLearningQueue.add(
+          //   'object-detection',
+          //   {
+          //     resizePath,
+          //   },
+          //   { jobId: randomUUID() },
+          // );
+        });
+    });
+
+    return 'ok';
+  }
 }

+ 18 - 4
server/src/modules/image-optimize/image-optimize.service.ts

@@ -7,12 +7,26 @@ import { AssetEntity } from '../../api-v1/asset/entities/asset.entity';
 import { AuthUserDto } from '../../decorators/auth-user.decorator';
 
 @Injectable()
-export class ImageOptimizeService {
-  constructor(@InjectQueue('image') private imageQueue: Queue) {}
+export class AssetOptimizeService {
+  constructor(@InjectQueue('optimize') private optimizeQueue: Queue) {}
 
   public async resizeImage(savedAsset: AssetEntity) {
-    const job = await this.imageQueue.add(
-      'optimize',
+    const job = await this.optimizeQueue.add(
+      'resize-image',
+      {
+        savedAsset,
+      },
+      { jobId: randomUUID() },
+    );
+
+    return {
+      jobId: job.id,
+    };
+  }
+
+  public async resizeVideo(savedAsset: AssetEntity) {
+    const job = await this.optimizeQueue.add(
+      'resize-video',
       {
         savedAsset,
       },