diff --git a/server/src/domain/media/media.service.spec.ts b/server/src/domain/media/media.service.spec.ts index 1d9031df75..753c4dd9e8 100644 --- a/server/src/domain/media/media.service.spec.ts +++ b/server/src/domain/media/media.service.spec.ts @@ -265,6 +265,30 @@ describe(MediaService.name, () => { }); }); + it('should always generate video thumbnail in one pass', async () => { + mediaMock.probe.mockResolvedValue(probeStub.videoStreamHDR); + configMock.load.mockResolvedValue([ + { key: SystemConfigKey.FFMPEG_TWO_PASS, value: true }, + { key: SystemConfigKey.FFMPEG_MAX_BITRATE, value: '5000k' }, + ]); + assetMock.getByIds.mockResolvedValue([assetStub.video]); + await sut.handleGenerateJpegThumbnail({ id: assetStub.video.id }); + + expect(mediaMock.transcode).toHaveBeenCalledWith( + '/original/path.ext', + 'upload/thumbs/user-id/as/se/asset-id.jpeg', + { + inputOptions: ['-ss 00:00:00', '-sws_flags accurate_rnd+bitexact+full_chroma_int'], + outputOptions: [ + '-frames:v 1', + '-v verbose', + '-vf zscale=t=linear:npl=100,tonemap=hable:desat=0,zscale=p=bt709:t=601:m=bt470bg:range=pc,format=yuv420p', + ], + twoPass: false, + }, + ); + }); + it('should run successfully', async () => { assetMock.getByIds.mockResolvedValue([assetStub.image]); await sut.handleGenerateJpegThumbnail({ id: assetStub.image.id }); diff --git a/server/src/domain/media/media.util.ts b/server/src/domain/media/media.util.ts index 75d2020944..e28d78e31d 100644 --- a/server/src/domain/media/media.util.ts +++ b/server/src/domain/media/media.util.ts @@ -278,6 +278,10 @@ export class ThumbnailConfig extends BaseConfig { return []; } + eligibleForTwoPass() { + return false; + } + getScaling(videoStream: VideoStreamInfo) { let options = super.getScaling(videoStream); options += ':flags=lanczos+accurate_rnd+bitexact+full_chroma_int';