mirror of
https://github.com/immich-app/immich.git
synced 2024-11-15 09:59:00 -07:00
feat(server): delete unnecessary encoded videos (#6027)
* delete unnecessary transcodes * added test
This commit is contained in:
parent
fd3a1a4da8
commit
a1e1f11399
@ -658,6 +658,21 @@ describe(MediaService.name, () => {
|
||||
expect(mediaMock.transcode).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should delete existing transcode if current policy does not require transcoding', async () => {
|
||||
const asset = assetStub.hasEncodedVideo;
|
||||
mediaMock.probe.mockResolvedValue(probeStub.videoStream2160p);
|
||||
configMock.load.mockResolvedValue([{ key: SystemConfigKey.FFMPEG_TRANSCODE, value: TranscodePolicy.DISABLED }]);
|
||||
assetMock.getByIds.mockResolvedValue([asset]);
|
||||
|
||||
await sut.handleVideoConversion({ id: asset.id });
|
||||
|
||||
expect(mediaMock.transcode).not.toHaveBeenCalled();
|
||||
expect(jobMock.queue).toHaveBeenCalledWith({
|
||||
name: JobName.DELETE_FILES,
|
||||
data: { files: [asset.encodedVideoPath] },
|
||||
});
|
||||
});
|
||||
|
||||
it('should set max bitrate if above 0', async () => {
|
||||
mediaMock.probe.mockResolvedValue(probeStub.matroskaContainer);
|
||||
configMock.load.mockResolvedValue([{ key: SystemConfigKey.FFMPEG_MAX_BITRATE, value: '4500k' }]);
|
||||
|
@ -241,11 +241,22 @@ export class MediaService {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!mainVideoStream.height || !mainVideoStream.width) {
|
||||
this.logger.warn(`Skipped transcoding for asset ${asset.id}: no video streams found`);
|
||||
return false;
|
||||
}
|
||||
|
||||
const { ffmpeg: config } = await this.configCore.getConfig();
|
||||
|
||||
const required = this.isTranscodeRequired(asset, mainVideoStream, mainAudioStream, containerExtension, config);
|
||||
if (!required) {
|
||||
return false;
|
||||
if (asset.encodedVideoPath) {
|
||||
this.logger.log(`Transcoded video exists for asset ${asset.id}, but is no longer required. Deleting...`);
|
||||
await this.jobRepository.queue({ name: JobName.DELETE_FILES, data: { files: [asset.encodedVideoPath] } });
|
||||
await this.assetRepository.save({ id: asset.id, encodedVideoPath: null });
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
let transcodeOptions;
|
||||
@ -289,11 +300,6 @@ export class MediaService {
|
||||
containerExtension: string,
|
||||
ffmpegConfig: SystemConfigFFmpegDto,
|
||||
): boolean {
|
||||
if (!videoStream.height || !videoStream.width) {
|
||||
this.logger.error('Skipping transcode, height or width undefined for video stream');
|
||||
return false;
|
||||
}
|
||||
|
||||
const isTargetVideoCodec = videoStream.codecName === ffmpegConfig.targetVideoCodec;
|
||||
const isTargetContainer = ['mov,mp4,m4a,3gp,3g2,mj2', 'mp4', 'mov'].includes(containerExtension);
|
||||
const isTargetAudioCodec = audioStream == null || audioStream.codecName === ffmpegConfig.targetAudioCodec;
|
||||
|
40
server/test/fixtures/asset.stub.ts
vendored
40
server/test/fixtures/asset.stub.ts
vendored
@ -545,4 +545,44 @@ export const assetStub = {
|
||||
sidecarPath: '/original/path.ext.xmp',
|
||||
deletedAt: null,
|
||||
}),
|
||||
|
||||
hasEncodedVideo: Object.freeze<AssetEntity>({
|
||||
id: 'asset-id',
|
||||
originalFileName: 'asset-id.ext',
|
||||
deviceAssetId: 'device-asset-id',
|
||||
fileModifiedAt: new Date('2023-02-23T05:06:29.716Z'),
|
||||
fileCreatedAt: new Date('2023-02-23T05:06:29.716Z'),
|
||||
owner: userStub.user1,
|
||||
ownerId: 'user-id',
|
||||
deviceId: 'device-id',
|
||||
originalPath: '/original/path.ext',
|
||||
resizePath: '/uploads/user-id/thumbs/path.ext',
|
||||
checksum: Buffer.from('file hash', 'utf8'),
|
||||
type: AssetType.VIDEO,
|
||||
webpPath: null,
|
||||
thumbhash: null,
|
||||
encodedVideoPath: '/encoded/video/path.mp4',
|
||||
createdAt: new Date('2023-02-23T05:06:29.716Z'),
|
||||
updatedAt: new Date('2023-02-23T05:06:29.716Z'),
|
||||
localDateTime: new Date('2023-02-23T05:06:29.716Z'),
|
||||
isFavorite: true,
|
||||
isArchived: false,
|
||||
isReadOnly: false,
|
||||
isExternal: false,
|
||||
isOffline: false,
|
||||
libraryId: 'library-id',
|
||||
library: libraryStub.uploadLibrary1,
|
||||
duration: null,
|
||||
isVisible: true,
|
||||
livePhotoVideo: null,
|
||||
livePhotoVideoId: null,
|
||||
tags: [],
|
||||
sharedLinks: [],
|
||||
faces: [],
|
||||
sidecarPath: null,
|
||||
exifInfo: {
|
||||
fileSizeInByte: 100_000,
|
||||
} as ExifEntity,
|
||||
deletedAt: null,
|
||||
}),
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user