mirror of
https://github.com/immich-app/immich.git
synced 2025-01-01 08:31:59 +00:00
Added creation date for video from ffmpeg.prob (#303)
This commit is contained in:
parent
b6814fad57
commit
97d9b80baa
3 changed files with 34 additions and 18 deletions
|
@ -15,7 +15,7 @@ import {
|
||||||
exifExtractionProcessorName,
|
exifExtractionProcessorName,
|
||||||
generateJPEGThumbnailProcessorName,
|
generateJPEGThumbnailProcessorName,
|
||||||
mp4ConversionProcessorName,
|
mp4ConversionProcessorName,
|
||||||
videoLengthExtractionProcessorName,
|
videoMetadataExtractionProcessorName,
|
||||||
} from '@app/job';
|
} from '@app/job';
|
||||||
|
|
||||||
@Processor(assetUploadedQueueName)
|
@Processor(assetUploadedQueueName)
|
||||||
|
@ -62,9 +62,9 @@ export class AssetUploadedProcessor {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extract video duration if uploaded from the web
|
// Extract video duration if uploaded from the web & CLI
|
||||||
if (asset.type == AssetType.VIDEO && asset.duration == '0:00:00.000000') {
|
if (asset.type == AssetType.VIDEO && asset.duration == '0:00:00.000000') {
|
||||||
await this.metadataExtractionQueue.add(videoLengthExtractionProcessorName, { asset }, { jobId: randomUUID() });
|
await this.metadataExtractionQueue.add(videoMetadataExtractionProcessorName, { asset }, { jobId: randomUUID() });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ import {
|
||||||
exifExtractionProcessorName,
|
exifExtractionProcessorName,
|
||||||
imageTaggingProcessorName,
|
imageTaggingProcessorName,
|
||||||
objectDetectionProcessorName,
|
objectDetectionProcessorName,
|
||||||
videoLengthExtractionProcessorName,
|
videoMetadataExtractionProcessorName,
|
||||||
metadataExtractionQueueName,
|
metadataExtractionQueueName,
|
||||||
} from '@app/job';
|
} from '@app/job';
|
||||||
|
|
||||||
|
@ -140,26 +140,42 @@ export class MetadataExtractionProcessor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Process({ name: videoLengthExtractionProcessorName, concurrency: 2 })
|
@Process({ name: videoMetadataExtractionProcessorName, concurrency: 2 })
|
||||||
async extractVideoLength(job: Job<IVideoLengthExtractionProcessor>) {
|
async extractVideoMetadata(job: Job<IVideoLengthExtractionProcessor>) {
|
||||||
const { asset } = job.data;
|
const { asset } = job.data;
|
||||||
|
|
||||||
ffmpeg.ffprobe(asset.originalPath, async (err, data) => {
|
ffmpeg.ffprobe(asset.originalPath, async (err, data) => {
|
||||||
if (!err) {
|
if (!err) {
|
||||||
|
let durationString = asset.duration;
|
||||||
|
let createdAt = asset.createdAt;
|
||||||
|
|
||||||
if (data.format.duration) {
|
if (data.format.duration) {
|
||||||
const videoDurationInSecond = parseInt(data.format.duration.toString(), 0);
|
durationString = this.extractDuration(data.format.duration);
|
||||||
|
|
||||||
const hours = Math.floor(videoDurationInSecond / 3600);
|
|
||||||
const minutes = Math.floor((videoDurationInSecond - hours * 3600) / 60);
|
|
||||||
const seconds = videoDurationInSecond - hours * 3600 - minutes * 60;
|
|
||||||
|
|
||||||
const durationString = `${hours}:${minutes < 10 ? '0' + minutes.toString() : minutes}:${
|
|
||||||
seconds < 10 ? '0' + seconds.toString() : seconds
|
|
||||||
}.000000`;
|
|
||||||
|
|
||||||
await this.assetRepository.update({ id: asset.id }, { duration: durationString });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const videoTags = data.format.tags;
|
||||||
|
if (videoTags) {
|
||||||
|
if (videoTags['com.apple.quicktime.creationdate']) {
|
||||||
|
createdAt = String(videoTags['com.apple.quicktime.creationdate']);
|
||||||
|
} else {
|
||||||
|
createdAt = String(videoTags['creation_time']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.assetRepository.update({ id: asset.id }, { duration: durationString, createdAt: createdAt });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private extractDuration(duration: number) {
|
||||||
|
const videoDurationInSecond = parseInt(duration.toString(), 0);
|
||||||
|
|
||||||
|
const hours = Math.floor(videoDurationInSecond / 3600);
|
||||||
|
const minutes = Math.floor((videoDurationInSecond - hours * 3600) / 60);
|
||||||
|
const seconds = videoDurationInSecond - hours * 3600 - minutes * 60;
|
||||||
|
|
||||||
|
return `${hours}:${minutes < 10 ? '0' + minutes.toString() : minutes}:${
|
||||||
|
seconds < 10 ? '0' + seconds.toString() : seconds
|
||||||
|
}.000000`;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,6 @@ export const generateWEBPThumbnailProcessorName = 'generate-webp-thumbnail';
|
||||||
* Metadata Extraction Queue Jobs
|
* Metadata Extraction Queue Jobs
|
||||||
*/
|
*/
|
||||||
export const exifExtractionProcessorName = 'exif-extraction';
|
export const exifExtractionProcessorName = 'exif-extraction';
|
||||||
export const videoLengthExtractionProcessorName = 'extract-video-length';
|
export const videoMetadataExtractionProcessorName = 'extract-video-metadata';
|
||||||
export const objectDetectionProcessorName = 'detect-object';
|
export const objectDetectionProcessorName = 'detect-object';
|
||||||
export const imageTaggingProcessorName = 'tag-image';
|
export const imageTaggingProcessorName = 'tag-image';
|
||||||
|
|
Loading…
Reference in a new issue