diff --git a/README.md b/README.md index b3921a2cdb..e0e5d4015a 100644 --- a/README.md +++ b/README.md @@ -36,11 +36,13 @@ This project is under heavy development, there will be continous functions, feat [x] Auto Backup +[x] Support HEIC + # Development You can use docker compose for development, there are several services that compose Immich -1. The server +1. NestJs 2. PostgreSQL 3. Redis 4. Nginx diff --git a/mobile/lib/modules/home/ui/thumbnail_image.dart b/mobile/lib/modules/home/ui/thumbnail_image.dart index ae8208186c..6d35749933 100644 --- a/mobile/lib/modules/home/ui/thumbnail_image.dart +++ b/mobile/lib/modules/home/ui/thumbnail_image.dart @@ -49,7 +49,6 @@ class ThumbnailImage extends HookConsumerWidget { } else if (isMultiSelectEnable && !selectedAsset.contains(asset)) { ref.watch(homePageStateProvider.notifier).addSingleSelectedItem(asset); } else { - print(asset.id); if (asset.type == 'IMAGE') { AutoRouter.of(context).push( ImageViewerRoute( diff --git a/mobile/lib/modules/login/ui/login_form.dart b/mobile/lib/modules/login/ui/login_form.dart index 6d878d22d5..cdb801c4ee 100644 --- a/mobile/lib/modules/login/ui/login_form.dart +++ b/mobile/lib/modules/login/ui/login_form.dart @@ -126,7 +126,7 @@ class LoginButton extends ConsumerWidget { } else { ImmichToast.show( context: context, - msg: "Error logging you in, check server url, emald and password!", + msg: "Error logging you in, check server url, email and password!", toastType: ToastType.error); } }, diff --git a/mobile/lib/shared/services/backup.service.dart b/mobile/lib/shared/services/backup.service.dart index 08195ec9e2..1237ea3739 100644 --- a/mobile/lib/shared/services/backup.service.dart +++ b/mobile/lib/shared/services/backup.service.dart @@ -37,20 +37,12 @@ class BackupService { for (var entity in assetList) { try { if (entity.type == AssetType.video) { - file = await entity.file; + file = await entity.originFile; } else { - file = await entity.file.timeout(const Duration(seconds: 5)); + file = await entity.originFile.timeout(const Duration(seconds: 5)); } if (file != null) { - // reading exif - // var exifData = await readExifFromFile(file); - - // for (String key in exifData.keys) { - // debugPrint("- $key (${exifData[key]?.tagType}): ${exifData[key]}"); - // } - - // debugPrint("------------------"); String originalFileName = await entity.titleAsync; String fileNameWithoutPath = originalFileName.toString().split(".")[0]; var fileExtension = p.extension(file.path); diff --git a/mobile/lib/utils/files_helper.dart b/mobile/lib/utils/files_helper.dart index 787a67a716..b2e1b5e7ee 100644 --- a/mobile/lib/utils/files_helper.dart +++ b/mobile/lib/utils/files_helper.dart @@ -1,9 +1,7 @@ -import 'package:flutter/material.dart'; import 'package:path/path.dart' as p; class FileHelper { static getMimeType(String filePath) { - debugPrint(filePath); var fileExtension = p.extension(filePath).split(".")[1]; switch (fileExtension.toLowerCase()) { @@ -28,6 +26,12 @@ class FileHelper { case 'avi': return {"type": "video", "subType": "x-msvideo"}; + case 'heic': + return {"type": "image", "subType": "heic"}; + + case 'heif': + return {"type": "image", "subType": "heif"}; + default: return {"type": "unsupport", "subType": "unsupport"}; } diff --git a/mobile/pubspec.lock b/mobile/pubspec.lock index 9df915f441..b566ebb8e1 100644 --- a/mobile/pubspec.lock +++ b/mobile/pubspec.lock @@ -513,6 +513,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.12.11" + material_color_utilities: + dependency: transitive + description: + name: material_color_utilities + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.3" meta: dependency: transitive description: @@ -818,7 +825,7 @@ packages: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.4.3" + version: "0.4.8" timing: dependency: transitive description: diff --git a/server/Dockerfile b/server/Dockerfile index 439057f507..5e51376524 100644 --- a/server/Dockerfile +++ b/server/Dockerfile @@ -1,7 +1,7 @@ ################################## # DEVELOPMENT ################################## -FROM node:16-bullseye-slim AS development +FROM node:16-alpine3.14 AS development ARG DEBIAN_FRONTEND=noninteractive @@ -9,8 +9,7 @@ WORKDIR /usr/src/app COPY package.json package-lock.json ./ -RUN apt-get update -RUN apt-get install gcc g++ make cmake python3 python3-pip ffmpeg -y +RUN apk add --update-cache build-base python3 libheif vips-dev vips ffmpeg RUN npm install @@ -18,15 +17,6 @@ COPY . . RUN npm run build -# Clean up commands -RUN apt-get autoremove -y && apt-get clean && \ - rm -rf /usr/local/src/* - -RUN apt-get clean && \ - rm -rf /var/lib/apt/lists/* - - - ################################## # PRODUCTION ################################## diff --git a/server/package-lock.json b/server/package-lock.json index 6b4e1749dd..9a7b2037bf 100644 --- a/server/package-lock.json +++ b/server/package-lock.json @@ -19,17 +19,13 @@ "@nestjs/platform-express": "^8.0.0", "@nestjs/platform-fastify": "^8.2.6", "@nestjs/typeorm": "^8.0.3", - "@tensorflow-models/coco-ssd": "^2.2.2", - "@tensorflow/tfjs": "^3.13.0", - "@tensorflow/tfjs-converter": "^3.13.0", - "@tensorflow/tfjs-core": "^3.13.0", - "@tensorflow/tfjs-node": "^3.13.0", "bcrypt": "^5.0.1", "bull": "^4.4.0", "class-transformer": "^0.5.1", "class-validator": "^0.13.2", "dotenv": "^14.2.0", "fluent-ffmpeg": "^2.1.2", + "heic-convert": "^1.2.4", "joi": "^17.5.0", "lodash": "^4.17.21", "passport": "^0.5.2", @@ -38,7 +34,7 @@ "reflect-metadata": "^0.1.13", "rimraf": "^3.0.2", "rxjs": "^7.2.0", - "sharp": "^0.29.3", + "sharp": "0.28", "systeminformation": "^5.11.0", "typeorm": "^0.2.41" }, @@ -3723,12 +3719,12 @@ "dev": true }, "node_modules/color": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/color/-/color-4.2.0.tgz", - "integrity": "sha512-hHTcrbvEnGjC7WBMk6ibQWFVDgEFTVmjrz2Q5HlU6ltwxv0JJN2Z8I7uRbWeQLF04dikxs8zgyZkazRJvSMtyQ==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz", + "integrity": "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==", "dependencies": { - "color-convert": "^2.0.1", - "color-string": "^1.9.0" + "color-convert": "^1.9.3", + "color-string": "^1.6.0" } }, "node_modules/color-convert": { @@ -3756,6 +3752,19 @@ "simple-swizzle": "^0.2.2" } }, + "node_modules/color/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + }, "node_modules/colors": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", @@ -4069,17 +4078,14 @@ "dev": true }, "node_modules/decompress-response": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", - "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz", + "integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==", "dependencies": { - "mimic-response": "^3.1.0" + "mimic-response": "^2.0.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, "node_modules/dedent": { @@ -5650,6 +5656,30 @@ "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" }, + "node_modules/heic-convert": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/heic-convert/-/heic-convert-1.2.4.tgz", + "integrity": "sha512-klJHyv+BqbgKiCQvCqI9IKIvweCcohDuDl0Jphearj8+16+v8eff2piVevHqq4dW9TK0r1onTR6PKHP1I4hdbA==", + "dependencies": { + "heic-decode": "^1.1.2", + "jpeg-js": "^0.4.1", + "pngjs": "^3.4.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/heic-decode": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/heic-decode/-/heic-decode-1.1.2.tgz", + "integrity": "sha512-UF8teegxvzQPdSTcx5frIUhitNDliz/9Pui0JFdIqVRE00spVE33DcCYtZqaLNyd4y5RP/QQWZFIc1YWVKKm2A==", + "dependencies": { + "libheif-js": "^1.10.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, "node_modules/hexoid": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/hexoid/-/hexoid-1.0.0.tgz", @@ -6864,6 +6894,11 @@ "@sideway/pinpoint": "^2.0.0" } }, + "node_modules/jpeg-js": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.4.3.tgz", + "integrity": "sha512-ru1HWKek8octvUHFHvE5ZzQ1yAsJmIvRdGWvSoKV52XKyuyYA437QWDttXT8eZXDSbuMpHlLzPDZUPd6idIz+Q==" + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -7076,6 +7111,14 @@ "node": ">= 0.8.0" } }, + "node_modules/libheif-js": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/libheif-js/-/libheif-js-1.12.0.tgz", + "integrity": "sha512-hDs6xQ7028VOwAFwEtM0Q+B2x2NW69Jb2MhQFUbk3rUrHzz4qo5mqS8VrqNgYnSc8TiUGnR691LnO4uIfEE23w==", + "engines": { + "node": ">=8.0.0" + } + }, "node_modules/libphonenumber-js": { "version": "1.9.48", "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.9.48.tgz", @@ -7419,11 +7462,11 @@ } }, "node_modules/mimic-response": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", - "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz", + "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==", "engines": { - "node": ">=10" + "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -7574,14 +7617,19 @@ "dev": true }, "node_modules/node-abi": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.8.0.tgz", - "integrity": "sha512-tzua9qWWi7iW4I42vUPKM+SfaF0vQSLAm4yO5J83mSwB7GeoWrDKC/K+8YCnYNwqP5duwazbw2X9l4m8SC2cUw==", + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.30.1.tgz", + "integrity": "sha512-/2D0wOQPgaUWzVSVgRMx+trKJRC2UG4SUc4oCJoXx9Uxjtp0Vy3/kt7zcbxHF8+Z/pK3UloLWzBISg72brfy1w==", "dependencies": { - "semver": "^7.3.5" - }, - "engines": { - "node": ">=10" + "semver": "^5.4.1" + } + }, + "node_modules/node-abi/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "bin": { + "semver": "bin/semver" } }, "node_modules/node-addon-api": { @@ -8196,6 +8244,14 @@ "node": ">=4" } }, + "node_modules/pngjs": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-3.4.0.tgz", + "integrity": "sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w==", + "engines": { + "node": ">=4.0.0" + } + }, "node_modules/postgres-array": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", @@ -8232,21 +8288,21 @@ } }, "node_modules/prebuild-install": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.0.1.tgz", - "integrity": "sha512-QBSab31WqkyxpnMWQxubYAHR5S9B2+r81ucocew34Fkl98FhvKIF50jIJnNOBmAZfyNV7vE5T6gd3hTVWgY6tg==", + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-6.1.4.tgz", + "integrity": "sha512-Z4vpywnK1lBg+zdPCVCsKq0xO66eEV9rWo2zrROGGiRS4JtueBOdlB1FnY8lcy7JsUud/Q3ijUxyWN26Ika0vQ==", "dependencies": { - "detect-libc": "^2.0.0", + "detect-libc": "^1.0.3", "expand-template": "^2.0.3", "github-from-package": "0.0.0", "minimist": "^1.2.3", "mkdirp-classic": "^0.5.3", "napi-build-utils": "^1.0.1", - "node-abi": "^3.3.0", + "node-abi": "^2.21.0", "npmlog": "^4.0.1", "pump": "^3.0.0", "rc": "^1.2.7", - "simple-get": "^4.0.0", + "simple-get": "^3.0.3", "tar-fs": "^2.0.0", "tunnel-agent": "^0.6.0" }, @@ -8254,15 +8310,7 @@ "prebuild-install": "bin.js" }, "engines": { - "node": ">=10" - } - }, - "node_modules/prebuild-install/node_modules/detect-libc": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.0.tgz", - "integrity": "sha512-S55LzUl8HUav8l9E2PBTlC5PAJrHK7tkM+XXFGD+fbsbkTzhCpG6K05LxJcUOEWzMa4v6ptcMZ9s3fOdJDu0Zw==", - "engines": { - "node": ">=8" + "node": ">=6" } }, "node_modules/prelude-ls": { @@ -8922,32 +8970,27 @@ } }, "node_modules/sharp": { - "version": "0.29.3", - "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.29.3.tgz", - "integrity": "sha512-fKWUuOw77E4nhpyzCCJR1ayrttHoFHBT2U/kR/qEMRhvPEcluG4BKj324+SCO1e84+knXHwhJ1HHJGnUt4ElGA==", + "version": "0.28.3", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.28.3.tgz", + "integrity": "sha512-21GEP45Rmr7q2qcmdnjDkNP04Ooh5v0laGS5FDpojOO84D1DJwUijLiSq8XNNM6e8aGXYtoYRh3sVNdm8NodMA==", "hasInstallScript": true, "dependencies": { - "color": "^4.0.1", + "color": "^3.1.3", "detect-libc": "^1.0.3", - "node-addon-api": "^4.2.0", - "prebuild-install": "^7.0.0", + "node-addon-api": "^3.2.0", + "prebuild-install": "^6.1.2", "semver": "^7.3.5", - "simple-get": "^4.0.0", + "simple-get": "^3.1.0", "tar-fs": "^2.1.1", "tunnel-agent": "^0.6.0" }, "engines": { - "node": ">=12.13.0" + "node": ">=10" }, "funding": { "url": "https://opencollective.com/libvips" } }, - "node_modules/sharp/node_modules/node-addon-api": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-4.3.0.tgz", - "integrity": "sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==" - }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -9025,25 +9068,11 @@ ] }, "node_modules/simple-get": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", - "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.1.tgz", + "integrity": "sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA==", "dependencies": { - "decompress-response": "^6.0.0", + "decompress-response": "^4.2.0", "once": "^1.3.1", "simple-concat": "^1.0.0" } @@ -13491,12 +13520,27 @@ "dev": true }, "color": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/color/-/color-4.2.0.tgz", - "integrity": "sha512-hHTcrbvEnGjC7WBMk6ibQWFVDgEFTVmjrz2Q5HlU6ltwxv0JJN2Z8I7uRbWeQLF04dikxs8zgyZkazRJvSMtyQ==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz", + "integrity": "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==", "requires": { - "color-convert": "^2.0.1", - "color-string": "^1.9.0" + "color-convert": "^1.9.3", + "color-string": "^1.6.0" + }, + "dependencies": { + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + } } }, "color-convert": { @@ -13783,11 +13827,11 @@ "dev": true }, "decompress-response": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", - "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz", + "integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==", "requires": { - "mimic-response": "^3.1.0" + "mimic-response": "^2.0.0" } }, "dedent": { @@ -15001,6 +15045,24 @@ "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" }, + "heic-convert": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/heic-convert/-/heic-convert-1.2.4.tgz", + "integrity": "sha512-klJHyv+BqbgKiCQvCqI9IKIvweCcohDuDl0Jphearj8+16+v8eff2piVevHqq4dW9TK0r1onTR6PKHP1I4hdbA==", + "requires": { + "heic-decode": "^1.1.2", + "jpeg-js": "^0.4.1", + "pngjs": "^3.4.0" + } + }, + "heic-decode": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/heic-decode/-/heic-decode-1.1.2.tgz", + "integrity": "sha512-UF8teegxvzQPdSTcx5frIUhitNDliz/9Pui0JFdIqVRE00spVE33DcCYtZqaLNyd4y5RP/QQWZFIc1YWVKKm2A==", + "requires": { + "libheif-js": "^1.10.0" + } + }, "hexoid": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/hexoid/-/hexoid-1.0.0.tgz", @@ -15922,6 +15984,11 @@ "@sideway/pinpoint": "^2.0.0" } }, + "jpeg-js": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.4.3.tgz", + "integrity": "sha512-ru1HWKek8octvUHFHvE5ZzQ1yAsJmIvRdGWvSoKV52XKyuyYA437QWDttXT8eZXDSbuMpHlLzPDZUPd6idIz+Q==" + }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -16097,6 +16164,11 @@ "type-check": "~0.4.0" } }, + "libheif-js": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/libheif-js/-/libheif-js-1.12.0.tgz", + "integrity": "sha512-hDs6xQ7028VOwAFwEtM0Q+B2x2NW69Jb2MhQFUbk3rUrHzz4qo5mqS8VrqNgYnSc8TiUGnR691LnO4uIfEE23w==" + }, "libphonenumber-js": { "version": "1.9.48", "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.9.48.tgz", @@ -16376,9 +16448,9 @@ "dev": true }, "mimic-response": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", - "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==" + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz", + "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==" }, "minimatch": { "version": "3.0.4", @@ -16506,11 +16578,18 @@ "dev": true }, "node-abi": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.8.0.tgz", - "integrity": "sha512-tzua9qWWi7iW4I42vUPKM+SfaF0vQSLAm4yO5J83mSwB7GeoWrDKC/K+8YCnYNwqP5duwazbw2X9l4m8SC2cUw==", + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.30.1.tgz", + "integrity": "sha512-/2D0wOQPgaUWzVSVgRMx+trKJRC2UG4SUc4oCJoXx9Uxjtp0Vy3/kt7zcbxHF8+Z/pK3UloLWzBISg72brfy1w==", "requires": { - "semver": "^7.3.5" + "semver": "^5.4.1" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + } } }, "node-addon-api": { @@ -16968,6 +17047,11 @@ "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", "dev": true }, + "pngjs": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-3.4.0.tgz", + "integrity": "sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w==" + }, "postgres-array": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", @@ -16992,30 +17076,23 @@ } }, "prebuild-install": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.0.1.tgz", - "integrity": "sha512-QBSab31WqkyxpnMWQxubYAHR5S9B2+r81ucocew34Fkl98FhvKIF50jIJnNOBmAZfyNV7vE5T6gd3hTVWgY6tg==", + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-6.1.4.tgz", + "integrity": "sha512-Z4vpywnK1lBg+zdPCVCsKq0xO66eEV9rWo2zrROGGiRS4JtueBOdlB1FnY8lcy7JsUud/Q3ijUxyWN26Ika0vQ==", "requires": { - "detect-libc": "^2.0.0", + "detect-libc": "^1.0.3", "expand-template": "^2.0.3", "github-from-package": "0.0.0", "minimist": "^1.2.3", "mkdirp-classic": "^0.5.3", "napi-build-utils": "^1.0.1", - "node-abi": "^3.3.0", + "node-abi": "^2.21.0", "npmlog": "^4.0.1", "pump": "^3.0.0", "rc": "^1.2.7", - "simple-get": "^4.0.0", + "simple-get": "^3.0.3", "tar-fs": "^2.0.0", "tunnel-agent": "^0.6.0" - }, - "dependencies": { - "detect-libc": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.0.tgz", - "integrity": "sha512-S55LzUl8HUav8l9E2PBTlC5PAJrHK7tkM+XXFGD+fbsbkTzhCpG6K05LxJcUOEWzMa4v6ptcMZ9s3fOdJDu0Zw==" - } } }, "prelude-ls": { @@ -17497,25 +17574,18 @@ } }, "sharp": { - "version": "0.29.3", - "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.29.3.tgz", - "integrity": "sha512-fKWUuOw77E4nhpyzCCJR1ayrttHoFHBT2U/kR/qEMRhvPEcluG4BKj324+SCO1e84+knXHwhJ1HHJGnUt4ElGA==", + "version": "0.28.3", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.28.3.tgz", + "integrity": "sha512-21GEP45Rmr7q2qcmdnjDkNP04Ooh5v0laGS5FDpojOO84D1DJwUijLiSq8XNNM6e8aGXYtoYRh3sVNdm8NodMA==", "requires": { - "color": "^4.0.1", + "color": "^3.1.3", "detect-libc": "^1.0.3", - "node-addon-api": "^4.2.0", - "prebuild-install": "^7.0.0", + "node-addon-api": "^3.2.0", + "prebuild-install": "^6.1.2", "semver": "^7.3.5", - "simple-get": "^4.0.0", + "simple-get": "^3.1.0", "tar-fs": "^2.1.1", "tunnel-agent": "^0.6.0" - }, - "dependencies": { - "node-addon-api": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-4.3.0.tgz", - "integrity": "sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==" - } } }, "shebang-command": { @@ -17566,11 +17636,11 @@ "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==" }, "simple-get": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", - "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.1.tgz", + "integrity": "sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA==", "requires": { - "decompress-response": "^6.0.0", + "decompress-response": "^4.2.0", "once": "^1.3.1", "simple-concat": "^1.0.0" } diff --git a/server/package.json b/server/package.json index b758704676..bba6e51836 100644 --- a/server/package.json +++ b/server/package.json @@ -50,7 +50,7 @@ "reflect-metadata": "^0.1.13", "rimraf": "^3.0.2", "rxjs": "^7.2.0", - "sharp": "^0.29.3", + "sharp": "0.28", "systeminformation": "^5.11.0", "typeorm": "^0.2.41" }, diff --git a/server/src/api-v1/asset/asset.module.ts b/server/src/api-v1/asset/asset.module.ts index 88e1a28e1d..161e00748a 100644 --- a/server/src/api-v1/asset/asset.module.ts +++ b/server/src/api-v1/asset/asset.module.ts @@ -17,14 +17,6 @@ import { BullModule } from '@nestjs/bull'; removeOnFail: false, }, }), - BullModule.registerQueue({ - name: 'machine-learning', - defaultJobOptions: { - attempts: 3, - removeOnComplete: true, - removeOnFail: false, - }, - }), TypeOrmModule.forFeature([AssetEntity]), ImageOptimizeModule, ], diff --git a/server/src/api-v1/asset/asset.service.ts b/server/src/api-v1/asset/asset.service.ts index 8196986efd..4d5c672f4d 100644 --- a/server/src/api-v1/asset/asset.service.ts +++ b/server/src/api-v1/asset/asset.service.ts @@ -8,7 +8,6 @@ import { AssetEntity, AssetType } from './entities/asset.entity'; import _ from 'lodash'; import { GetAllAssetQueryDto } from './dto/get-all-asset-query.dto'; import { GetAllAssetReponseDto } from './dto/get-all-asset-response.dto'; -import { Greater } from '@tensorflow/tfjs-core'; @Injectable() export class AssetService { diff --git a/server/src/config/multer-option.config.ts b/server/src/config/multer-option.config.ts index 7d6cd3652a..d69eebda14 100644 --- a/server/src/config/multer-option.config.ts +++ b/server/src/config/multer-option.config.ts @@ -11,7 +11,7 @@ export const multerConfig = { export const multerOption: MulterOptions = { fileFilter: (req: Request, file: any, cb: any) => { - if (file.mimetype.match(/\/(jpg|jpeg|png|gif|mp4|x-msvideo|quicktime)$/)) { + if (file.mimetype.match(/\/(jpg|jpeg|png|gif|mp4|x-msvideo|quicktime|heic|heif)$/)) { cb(null, true); } else { cb(new HttpException(`Unsupported file type ${extname(file.originalname)}`, HttpStatus.BAD_REQUEST), false); diff --git a/server/src/modules/image-optimize/image-optimize.module.ts b/server/src/modules/image-optimize/image-optimize.module.ts index 5d378e3aa0..603a8bc825 100644 --- a/server/src/modules/image-optimize/image-optimize.module.ts +++ b/server/src/modules/image-optimize/image-optimize.module.ts @@ -7,7 +7,6 @@ import { AssetService } from '../../api-v1/asset/asset.service'; import { AssetEntity } from '../../api-v1/asset/entities/asset.entity'; import { ImageOptimizeProcessor } from './image-optimize.processor'; import { AssetOptimizeService } from './image-optimize.service'; -import { MachineLearningProcessor } from './machine-learning.processor'; @Module({ imports: [ @@ -19,18 +18,10 @@ import { MachineLearningProcessor } from './machine-learning.processor'; removeOnFail: false, }, }), - BullModule.registerQueue({ - name: 'machine-learning', - defaultJobOptions: { - attempts: 3, - removeOnComplete: true, - removeOnFail: false, - }, - }), TypeOrmModule.forFeature([AssetEntity]), ], - providers: [AssetOptimizeService, ImageOptimizeProcessor, MachineLearningProcessor], + providers: [AssetOptimizeService, ImageOptimizeProcessor], exports: [AssetOptimizeService], }) export class ImageOptimizeModule {} diff --git a/server/src/modules/image-optimize/image-optimize.processor.ts b/server/src/modules/image-optimize/image-optimize.processor.ts index ae11c2e4da..269aa38247 100644 --- a/server/src/modules/image-optimize/image-optimize.processor.ts +++ b/server/src/modules/image-optimize/image-optimize.processor.ts @@ -4,16 +4,16 @@ import { Job, Queue } from 'bull'; import { Repository } from 'typeorm'; import { AssetEntity } from '../../api-v1/asset/entities/asset.entity'; import sharp from 'sharp'; -import fs, { existsSync, mkdirSync } from 'fs'; +import { existsSync, mkdirSync, readFile } from 'fs'; import { ConfigService } from '@nestjs/config'; import ffmpeg from 'fluent-ffmpeg'; -import { Logger } from '@nestjs/common'; @Processor('optimize') export class ImageOptimizeProcessor { constructor( - @InjectRepository(AssetEntity) private assetRepository: Repository, - @InjectQueue('machine-learning') private machineLearningQueue: Queue, + @InjectRepository(AssetEntity) + private assetRepository: Repository, + private configService: ConfigService, ) {} @@ -32,30 +32,42 @@ export class ImageOptimizeProcessor { mkdirSync(resizeDir, { recursive: true }); } - fs.readFile(savedAsset.originalPath, (err, data) => { + readFile(savedAsset.originalPath, async (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); - return; - } + if (savedAsset.mimeType == 'image/heic' || savedAsset.mimeType == 'image/heif') { + let desitnation = ''; + if (savedAsset.mimeType == 'image/heic') { + desitnation = resizePath.replace('.HEIC', '.jpeg'); + } else { + desitnation = resizePath.replace('.HEIF', '.jpeg'); + } - await this.assetRepository.update(savedAsset, { resizePath: resizePath }); + sharp(data) + .toFormat('jpeg') + .resize(512, 512, { fit: 'outside' }) + .toFile(desitnation, async (err, info) => { + if (err) { + console.error('Error resizing file ', err); + return; + } - // Send file to object detection after resizing - // const detectionJob = await this.machineLearningQueue.add( - // 'object-detection', - // { - // resizePath, - // }, - // { jobId: randomUUID() }, - // ); - }); + await this.assetRepository.update(savedAsset, { resizePath: desitnation }); + }); + } else { + sharp(data) + .resize(512, 512, { fit: 'outside' }) + .toFile(resizePath, async (err, info) => { + if (err) { + console.error('Error resizing file ', err); + return; + } + + await this.assetRepository.update(savedAsset, { resizePath: resizePath }); + }); + } }); return 'ok'; diff --git a/server/src/modules/image-optimize/machine-learning.processor.ts b/server/src/modules/image-optimize/machine-learning.processor.ts deleted file mode 100644 index fc3e0c61c8..0000000000 --- a/server/src/modules/image-optimize/machine-learning.processor.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { Process, Processor } from '@nestjs/bull'; -import { InjectRepository } from '@nestjs/typeorm'; -import { Job } from 'bull'; -import { Repository } from 'typeorm'; -import { AssetEntity } from '../../api-v1/asset/entities/asset.entity'; -import fs from 'fs'; -import { ConfigService } from '@nestjs/config'; -import * as tfnode from '@tensorflow/tfjs-node'; -import * as cocoSsd from '@tensorflow-models/coco-ssd'; - -@Processor('machine-learning') -export class MachineLearningProcessor { - constructor( - @InjectRepository(AssetEntity) private assetRepository: Repository, - private configService: ConfigService, - ) {} - - @Process('object-detection') - async handleOptimization(job: Job) { - try { - const { resizePath }: { resizePath: string } = job.data; - - const image = fs.readFileSync(resizePath); - const decodedImage = tfnode.node.decodeImage(image, 3) as tfnode.Tensor3D; - const model = await cocoSsd.load(); - const predictions = await model.detect(decodedImage); - console.log('\n\nstart predictions ------------------ '); - for (var result of predictions) { - console.log(`Found ${result.class} with score ${result.score}`); - } - console.log('end predictions ------------------\n\n'); - - return 'ok'; - } catch (e) { - console.log('Error object detection ', e); - } - } -}