mirror of
https://github.com/immich-app/immich.git
synced 2025-12-28 01:11:47 +03:00
feat (web/server) 360 degrees Web panoramas [attempt 2] (#3412)
* commit 1 (isPanorama: boolean) * working solution for projectiontypeenum * fix * format fix * fix * fix * fix * fix * enum projectiontype * working solution with exif * fix * reverted > * fix format * reverted auto-magic api.ts prettification * fix * reverted api.ts autogenerated * api ts regenerated * Update web/src/lib/components/assets/thumbnail/thumbnail.svelte Co-authored-by: Sergey Kondrikov <sergey.kondrikov@gmail.com> * Update web/src/lib/components/asset-viewer/asset-viewer.svelte Co-authored-by: Sergey Kondrikov <sergey.kondrikov@gmail.com> * exifProjectionType * Update server/src/microservices/processors/metadata-extraction.processor.ts Co-authored-by: Sergey Kondrikov <sergey.kondrikov@gmail.com> * projectionType?: string = ProjectionType.NONE; * not null * projectionType!: ProjectionType; * opeapi generator fix * fixes * fix * fix * generate api * asset.exifInifo?.projectionType * Update server/src/domain/asset/response-dto/exif-response.dto.ts Co-authored-by: Jason Rasmussen <jrasm91@gmail.com> * Update server/src/microservices/processors/metadata-extraction.processor.ts Co-authored-by: Jason Rasmussen <jrasm91@gmail.com> * enum -> varchar;projectiontypeenum->projectiontype * asset-viewer fixed prettiffier * @Column({}) single line * enum | string * make api * enum | string * enum | str fix * fix * chore: use string instead of enum * chore: open api * fix: checks --------- Co-authored-by: Sergey Kondrikov <sergey.kondrikov@gmail.com> Co-authored-by: Alex Tran <alex.tran1502@gmail.com> Co-authored-by: Jason Rasmussen <jrasm91@gmail.com>
This commit is contained in:
@@ -5553,6 +5553,11 @@
|
||||
"type": "string",
|
||||
"nullable": true,
|
||||
"default": null
|
||||
},
|
||||
"projectionType": {
|
||||
"type": "string",
|
||||
"nullable": true,
|
||||
"default": null
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
75
server/package-lock.json
generated
75
server/package-lock.json
generated
@@ -28,7 +28,7 @@
|
||||
"class-transformer": "^0.5.1",
|
||||
"class-validator": "^0.14.0",
|
||||
"cookie-parser": "^1.4.6",
|
||||
"exiftool-vendored": "^19.0.0",
|
||||
"exiftool-vendored": "^22.0.0",
|
||||
"exiftool-vendored.pl": "^12.54.0",
|
||||
"fluent-ffmpeg": "^2.1.2",
|
||||
"handlebars": "^4.7.7",
|
||||
@@ -4064,9 +4064,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/batch-cluster": {
|
||||
"version": "11.0.0",
|
||||
"resolved": "https://registry.npmjs.org/batch-cluster/-/batch-cluster-11.0.0.tgz",
|
||||
"integrity": "sha512-8iwqa+rKTaakOHkqdcXDT5L5117pa+FoP8/yAKpNdL44ZnC4V2NEA/sIg0ZO0O9NkpdjLk0A3efRFM5nVizqHw==",
|
||||
"version": "12.1.0",
|
||||
"resolved": "https://registry.npmjs.org/batch-cluster/-/batch-cluster-12.1.0.tgz",
|
||||
"integrity": "sha512-whGyJU4tr7kyg2USByu0/51mML5HsLAeNz5s03kMDYZNsQsGgDJgI47RdY3r7MciCjPkTaTD5O4eOVqOfEO7pg==",
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
}
|
||||
@@ -5976,25 +5976,25 @@
|
||||
}
|
||||
},
|
||||
"node_modules/exiftool-vendored": {
|
||||
"version": "19.0.0",
|
||||
"resolved": "https://registry.npmjs.org/exiftool-vendored/-/exiftool-vendored-19.0.0.tgz",
|
||||
"integrity": "sha512-Zes7TZrYWxts92mbF2Gs3drtWZucm4qsaeYaE6A+OOqmeD9UGaGisqIbyh9MilJrLi+ZHzWEJZtDj37QFf6xsA==",
|
||||
"version": "22.0.0",
|
||||
"resolved": "https://registry.npmjs.org/exiftool-vendored/-/exiftool-vendored-22.0.0.tgz",
|
||||
"integrity": "sha512-gBOQ4C2GLjxKPDPRuUbMOz91mG6IFA22L+Z/IQzFotFu20vc7YroqHALf/ophCbANA5sNSArbVDPijP7n/20Jg==",
|
||||
"dependencies": {
|
||||
"@photostructure/tz-lookup": "^7.0.0",
|
||||
"@types/luxon": "^3.2.0",
|
||||
"batch-cluster": "^11.0.0",
|
||||
"@types/luxon": "^3.3.0",
|
||||
"batch-cluster": "^12.1.0",
|
||||
"he": "^1.2.0",
|
||||
"luxon": "^3.2.1"
|
||||
"luxon": "^3.3.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"exiftool-vendored.exe": "12.54.0",
|
||||
"exiftool-vendored.pl": "12.54.0"
|
||||
"exiftool-vendored.exe": "12.62.0",
|
||||
"exiftool-vendored.pl": "12.62.0"
|
||||
}
|
||||
},
|
||||
"node_modules/exiftool-vendored.exe": {
|
||||
"version": "12.54.0",
|
||||
"resolved": "https://registry.npmjs.org/exiftool-vendored.exe/-/exiftool-vendored.exe-12.54.0.tgz",
|
||||
"integrity": "sha512-Dc4W6e0NtQfYuJIYK4piHfDJnd2jvA04e0aaq9R3Q1oO34KC5e+L1D2C7lFuZXqPQLYC1x3GYc/GVv5e+SkkrQ==",
|
||||
"version": "12.62.0",
|
||||
"resolved": "https://registry.npmjs.org/exiftool-vendored.exe/-/exiftool-vendored.exe-12.62.0.tgz",
|
||||
"integrity": "sha512-xNFkvmjwnMg6ivtmkc67w1qD23fIy06nRpMpGuBpTwTqAVatHV+vk7T75zyvLoXRRpd1rKID9XAVLGJCE/iiMQ==",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
@@ -6008,15 +6008,6 @@
|
||||
"!win32"
|
||||
]
|
||||
},
|
||||
"node_modules/exiftool-vendored/node_modules/exiftool-vendored.pl": {
|
||||
"version": "12.54.0",
|
||||
"resolved": "https://registry.npmjs.org/exiftool-vendored.pl/-/exiftool-vendored.pl-12.54.0.tgz",
|
||||
"integrity": "sha512-RBBowsYcM6EvbWoBkg2dOqHpH3WIzN7bIzHc+o+LquqCTo3doZwECClD/6PNHVSMQsl2Z0fEf75sNq2msooMSg==",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"!win32"
|
||||
]
|
||||
},
|
||||
"node_modules/exit": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz",
|
||||
@@ -15584,9 +15575,9 @@
|
||||
"integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog=="
|
||||
},
|
||||
"batch-cluster": {
|
||||
"version": "11.0.0",
|
||||
"resolved": "https://registry.npmjs.org/batch-cluster/-/batch-cluster-11.0.0.tgz",
|
||||
"integrity": "sha512-8iwqa+rKTaakOHkqdcXDT5L5117pa+FoP8/yAKpNdL44ZnC4V2NEA/sIg0ZO0O9NkpdjLk0A3efRFM5nVizqHw=="
|
||||
"version": "12.1.0",
|
||||
"resolved": "https://registry.npmjs.org/batch-cluster/-/batch-cluster-12.1.0.tgz",
|
||||
"integrity": "sha512-whGyJU4tr7kyg2USByu0/51mML5HsLAeNz5s03kMDYZNsQsGgDJgI47RdY3r7MciCjPkTaTD5O4eOVqOfEO7pg=="
|
||||
},
|
||||
"bcrypt": {
|
||||
"version": "5.1.0",
|
||||
@@ -17011,31 +17002,23 @@
|
||||
}
|
||||
},
|
||||
"exiftool-vendored": {
|
||||
"version": "19.0.0",
|
||||
"resolved": "https://registry.npmjs.org/exiftool-vendored/-/exiftool-vendored-19.0.0.tgz",
|
||||
"integrity": "sha512-Zes7TZrYWxts92mbF2Gs3drtWZucm4qsaeYaE6A+OOqmeD9UGaGisqIbyh9MilJrLi+ZHzWEJZtDj37QFf6xsA==",
|
||||
"version": "22.0.0",
|
||||
"resolved": "https://registry.npmjs.org/exiftool-vendored/-/exiftool-vendored-22.0.0.tgz",
|
||||
"integrity": "sha512-gBOQ4C2GLjxKPDPRuUbMOz91mG6IFA22L+Z/IQzFotFu20vc7YroqHALf/ophCbANA5sNSArbVDPijP7n/20Jg==",
|
||||
"requires": {
|
||||
"@photostructure/tz-lookup": "^7.0.0",
|
||||
"@types/luxon": "^3.2.0",
|
||||
"batch-cluster": "^11.0.0",
|
||||
"exiftool-vendored.exe": "12.54.0",
|
||||
"exiftool-vendored.pl": "12.54.0",
|
||||
"@types/luxon": "^3.3.0",
|
||||
"batch-cluster": "^12.1.0",
|
||||
"exiftool-vendored.exe": "12.62.0",
|
||||
"exiftool-vendored.pl": "12.62.0",
|
||||
"he": "^1.2.0",
|
||||
"luxon": "^3.2.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"exiftool-vendored.pl": {
|
||||
"version": "12.54.0",
|
||||
"resolved": "https://registry.npmjs.org/exiftool-vendored.pl/-/exiftool-vendored.pl-12.54.0.tgz",
|
||||
"integrity": "sha512-RBBowsYcM6EvbWoBkg2dOqHpH3WIzN7bIzHc+o+LquqCTo3doZwECClD/6PNHVSMQsl2Z0fEf75sNq2msooMSg==",
|
||||
"optional": true
|
||||
}
|
||||
"luxon": "^3.3.0"
|
||||
}
|
||||
},
|
||||
"exiftool-vendored.exe": {
|
||||
"version": "12.54.0",
|
||||
"resolved": "https://registry.npmjs.org/exiftool-vendored.exe/-/exiftool-vendored.exe-12.54.0.tgz",
|
||||
"integrity": "sha512-Dc4W6e0NtQfYuJIYK4piHfDJnd2jvA04e0aaq9R3Q1oO34KC5e+L1D2C7lFuZXqPQLYC1x3GYc/GVv5e+SkkrQ==",
|
||||
"version": "12.62.0",
|
||||
"resolved": "https://registry.npmjs.org/exiftool-vendored.exe/-/exiftool-vendored.exe-12.62.0.tgz",
|
||||
"integrity": "sha512-xNFkvmjwnMg6ivtmkc67w1qD23fIy06nRpMpGuBpTwTqAVatHV+vk7T75zyvLoXRRpd1rKID9XAVLGJCE/iiMQ==",
|
||||
"optional": true
|
||||
},
|
||||
"exiftool-vendored.pl": {
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
"class-transformer": "^0.5.1",
|
||||
"class-validator": "^0.14.0",
|
||||
"cookie-parser": "^1.4.6",
|
||||
"exiftool-vendored": "^19.0.0",
|
||||
"exiftool-vendored": "^22.0.0",
|
||||
"exiftool-vendored.pl": "^12.54.0",
|
||||
"fluent-ffmpeg": "^2.1.2",
|
||||
"handlebars": "^4.7.7",
|
||||
|
||||
@@ -24,6 +24,7 @@ export class ExifResponseDto {
|
||||
state?: string | null = null;
|
||||
country?: string | null = null;
|
||||
description?: string | null = null;
|
||||
projectionType?: string | null = null;
|
||||
}
|
||||
|
||||
export function mapExif(entity: ExifEntity): ExifResponseDto {
|
||||
@@ -48,5 +49,6 @@ export function mapExif(entity: ExifEntity): ExifResponseDto {
|
||||
state: entity.state,
|
||||
country: entity.country,
|
||||
description: entity.description,
|
||||
projectionType: entity.projectionType,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -43,6 +43,9 @@ export class ExifEntity {
|
||||
@Column({ type: 'float', nullable: true })
|
||||
longitude!: number | null;
|
||||
|
||||
@Column({ type: 'varchar', nullable: true })
|
||||
projectionType!: string | null;
|
||||
|
||||
@Column({ type: 'varchar', nullable: true })
|
||||
city!: string | null;
|
||||
|
||||
|
||||
13
server/src/infra/migrations/1690469489288-Panoramas.ts
Normal file
13
server/src/infra/migrations/1690469489288-Panoramas.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||
|
||||
export class Panoramas1690217088596 implements MigrationInterface {
|
||||
name = 'Panoramas1690217088596';
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`ALTER TABLE "exif" ADD "projectionType" character varying`);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`ALTER TABLE "exif" DROP COLUMN "projectionType"`);
|
||||
}
|
||||
}
|
||||
@@ -336,6 +336,12 @@ export class MetadataExtractionProcessor {
|
||||
await this.extractEmbeddedVideo(asset, offset, null, fileCreatedAt);
|
||||
}
|
||||
}
|
||||
|
||||
const projectionType = getExifProperty('ProjectionType');
|
||||
if (projectionType) {
|
||||
newExif.projectionType = String(projectionType).toUpperCase();
|
||||
}
|
||||
|
||||
newExif.livePhotoCID = getExifProperty('MediaGroupUUID');
|
||||
if (newExif.livePhotoCID && !asset.livePhotoVideoId) {
|
||||
const motionAsset = await this.assetRepository.findLivePhotoMatch({
|
||||
|
||||
@@ -625,6 +625,7 @@ const assetInfo: ExifResponseDto = {
|
||||
state: 'state',
|
||||
country: 'country',
|
||||
description: 'description',
|
||||
projectionType: null,
|
||||
};
|
||||
|
||||
const assetResponse: AssetResponseDto = {
|
||||
@@ -882,6 +883,7 @@ export const sharedLinkStub = {
|
||||
livePhotoVideoId: null,
|
||||
originalFileName: 'asset_1.jpeg',
|
||||
exifInfo: {
|
||||
projectionType: null,
|
||||
livePhotoCID: null,
|
||||
assetId: 'id_1',
|
||||
description: 'description',
|
||||
|
||||
Reference in New Issue
Block a user