mirror of
https://github.com/immich-app/immich.git
synced 2026-05-18 03:10:24 +03:00
refactor: move encoded video to asset files table (#26863)
* refactor: move encoded video to asset files table * chore: update
This commit is contained in:
@@ -163,7 +163,6 @@ const assetEntity = Object.freeze({
|
||||
fileCreatedAt: new Date('2022-06-19T23:41:36.910Z'),
|
||||
updatedAt: new Date('2022-06-19T23:41:36.910Z'),
|
||||
isFavorite: false,
|
||||
encodedVideoPath: '',
|
||||
duration: '0:00:00.000000',
|
||||
files: [] as AssetFile[],
|
||||
exifInfo: {
|
||||
@@ -711,13 +710,18 @@ describe(AssetMediaService.name, () => {
|
||||
});
|
||||
|
||||
it('should return the encoded video path if available', async () => {
|
||||
const asset = AssetFactory.create({ encodedVideoPath: '/path/to/encoded/video.mp4' });
|
||||
const asset = AssetFactory.from()
|
||||
.file({ type: AssetFileType.EncodedVideo, path: '/path/to/encoded/video.mp4' })
|
||||
.build();
|
||||
mocks.access.asset.checkOwnerAccess.mockResolvedValue(new Set([asset.id]));
|
||||
mocks.asset.getForVideo.mockResolvedValue(asset);
|
||||
mocks.asset.getForVideo.mockResolvedValue({
|
||||
originalPath: asset.originalPath,
|
||||
encodedVideoPath: asset.files[0].path,
|
||||
});
|
||||
|
||||
await expect(sut.playbackVideo(authStub.admin, asset.id)).resolves.toEqual(
|
||||
new ImmichFileResponse({
|
||||
path: asset.encodedVideoPath!,
|
||||
path: '/path/to/encoded/video.mp4',
|
||||
cacheControl: CacheControl.PrivateWithCache,
|
||||
contentType: 'video/mp4',
|
||||
}),
|
||||
@@ -727,7 +731,10 @@ describe(AssetMediaService.name, () => {
|
||||
it('should fall back to the original path', async () => {
|
||||
const asset = AssetFactory.create({ type: AssetType.Video, originalPath: '/original/path.ext' });
|
||||
mocks.access.asset.checkOwnerAccess.mockResolvedValue(new Set([asset.id]));
|
||||
mocks.asset.getForVideo.mockResolvedValue(asset);
|
||||
mocks.asset.getForVideo.mockResolvedValue({
|
||||
originalPath: asset.originalPath,
|
||||
encodedVideoPath: null,
|
||||
});
|
||||
|
||||
await expect(sut.playbackVideo(authStub.admin, asset.id)).resolves.toEqual(
|
||||
new ImmichFileResponse({
|
||||
|
||||
@@ -370,7 +370,7 @@ export class AssetService extends BaseService {
|
||||
assetFiles.editedFullsizeFile?.path,
|
||||
assetFiles.editedPreviewFile?.path,
|
||||
assetFiles.editedThumbnailFile?.path,
|
||||
asset.encodedVideoPath,
|
||||
assetFiles.encodedVideoFile?.path,
|
||||
];
|
||||
|
||||
if (deleteOnDisk && !asset.isOffline) {
|
||||
|
||||
@@ -2254,7 +2254,9 @@ describe(MediaService.name, () => {
|
||||
});
|
||||
|
||||
it('should delete existing transcode if current policy does not require transcoding', async () => {
|
||||
const asset = AssetFactory.create({ type: AssetType.Video, encodedVideoPath: '/encoded/video/path.mp4' });
|
||||
const asset = AssetFactory.from({ type: AssetType.Video })
|
||||
.file({ type: AssetFileType.EncodedVideo, path: '/encoded/video/path.mp4' })
|
||||
.build();
|
||||
mocks.media.probe.mockResolvedValue(probeStub.videoStream2160p);
|
||||
mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { transcode: TranscodePolicy.Disabled } });
|
||||
mocks.assetJob.getForVideoConversion.mockResolvedValue(asset);
|
||||
@@ -2264,7 +2266,7 @@ describe(MediaService.name, () => {
|
||||
expect(mocks.media.transcode).not.toHaveBeenCalled();
|
||||
expect(mocks.job.queue).toHaveBeenCalledWith({
|
||||
name: JobName.FileDelete,
|
||||
data: { files: [asset.encodedVideoPath] },
|
||||
data: { files: ['/encoded/video/path.mp4'] },
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ import {
|
||||
VideoInterfaces,
|
||||
VideoStreamInfo,
|
||||
} from 'src/types';
|
||||
import { getDimensions } from 'src/utils/asset.util';
|
||||
import { getAssetFile, getDimensions } from 'src/utils/asset.util';
|
||||
import { checkFaceVisibility, checkOcrVisibility } from 'src/utils/editor';
|
||||
import { BaseConfig, ThumbnailConfig } from 'src/utils/media';
|
||||
import { mimeTypes } from 'src/utils/mime-types';
|
||||
@@ -605,10 +605,11 @@ export class MediaService extends BaseService {
|
||||
let { ffmpeg } = await this.getConfig({ withCache: true });
|
||||
const target = this.getTranscodeTarget(ffmpeg, videoStream, audioStream);
|
||||
if (target === TranscodeTarget.None && !this.isRemuxRequired(ffmpeg, format)) {
|
||||
if (asset.encodedVideoPath) {
|
||||
const encodedVideo = getAssetFile(asset.files, AssetFileType.EncodedVideo, { isEdited: false });
|
||||
if (encodedVideo) {
|
||||
this.logger.log(`Transcoded video exists for asset ${asset.id}, but is no longer required. Deleting...`);
|
||||
await this.jobRepository.queue({ name: JobName.FileDelete, data: { files: [asset.encodedVideoPath] } });
|
||||
await this.assetRepository.update({ id: asset.id, encodedVideoPath: null });
|
||||
await this.jobRepository.queue({ name: JobName.FileDelete, data: { files: [encodedVideo.path] } });
|
||||
await this.assetRepository.deleteFiles([encodedVideo]);
|
||||
} else {
|
||||
this.logger.verbose(`Asset ${asset.id} does not require transcoding based on current policy, skipping`);
|
||||
}
|
||||
@@ -656,7 +657,12 @@ export class MediaService extends BaseService {
|
||||
|
||||
this.logger.log(`Successfully encoded ${asset.id}`);
|
||||
|
||||
await this.assetRepository.update({ id: asset.id, encodedVideoPath: output });
|
||||
await this.assetRepository.upsertFile({
|
||||
assetId: asset.id,
|
||||
type: AssetFileType.EncodedVideo,
|
||||
path: output,
|
||||
isEdited: false,
|
||||
});
|
||||
|
||||
return JobStatus.Success;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user