diff --git a/server/src/domain/media/media.service.spec.ts b/server/src/domain/media/media.service.spec.ts index 99c51a1c03..31754b9f38 100644 --- a/server/src/domain/media/media.service.spec.ts +++ b/server/src/domain/media/media.service.spec.ts @@ -259,6 +259,23 @@ describe(MediaService.name, () => { ); }); + it('should not scale resolution if no target resolution', async () => { + mediaMock.probe.mockResolvedValue(probeStub.videoStream2160p); + configMock.load.mockResolvedValue([ + { key: SystemConfigKey.FFMPEG_TRANSCODE, value: 'all' }, + { key: SystemConfigKey.FFMPEG_TARGET_RESOLUTION, value: 'original' }, + ]); + await sut.handleVideoConversion({ id: assetEntityStub.video.id }); + expect(mediaMock.transcode).toHaveBeenCalledWith( + '/original/path.ext', + 'upload/encoded-video/user-id/asset-id.mp4', + { + outputOptions: ['-vcodec h264', '-acodec aac', '-movflags faststart', '-preset ultrafast', '-crf 23'], + twoPass: false, + }, + ); + }); + it('should transcode with alternate scaling video is vertical', async () => { mediaMock.probe.mockResolvedValue(probeStub.videoStreamVertical2160p); configMock.load.mockResolvedValue([{ key: SystemConfigKey.FFMPEG_TRANSCODE, value: 'optimal' }]); diff --git a/server/src/domain/media/media.service.ts b/server/src/domain/media/media.service.ts index 7bab14c46a..5321631ab6 100644 --- a/server/src/domain/media/media.service.ts +++ b/server/src/domain/media/media.service.ts @@ -179,9 +179,9 @@ export class MediaService { ); const allTargetsMatching = isTargetVideoCodec && isTargetAudioCodec && isTargetContainer; - - const targetResolution = Number.parseInt(ffmpegConfig.targetResolution); - const isLargerThanTargetResolution = Math.min(videoStream.height, videoStream.width) > targetResolution; + const scalingEnabled = ffmpegConfig.targetResolution !== 'original'; + const targetRes = Number.parseInt(ffmpegConfig.targetResolution); + const isLargerThanTargetRes = scalingEnabled && Math.min(videoStream.height, videoStream.width) > targetRes; switch (ffmpegConfig.transcode) { case TranscodePreset.DISABLED: @@ -194,7 +194,7 @@ export class MediaService { return !allTargetsMatching; case TranscodePreset.OPTIMAL: - return !allTargetsMatching || isLargerThanTargetResolution; + return !allTargetsMatching || isLargerThanTargetRes; default: return false; @@ -212,10 +212,11 @@ export class MediaService { // video dimensions const videoIsRotated = Math.abs(stream.rotation) === 90; + const scalingEnabled = ffmpeg.targetResolution !== 'original'; const targetResolution = Number.parseInt(ffmpeg.targetResolution); const isVideoVertical = stream.height > stream.width || videoIsRotated; const scaling = isVideoVertical ? `${targetResolution}:-2` : `-2:${targetResolution}`; - const shouldScale = Math.min(stream.height, stream.width) > targetResolution; + const shouldScale = scalingEnabled && Math.min(stream.height, stream.width) > targetResolution; // video codec const isVP9 = ffmpeg.targetVideoCodec === 'vp9'; diff --git a/web/src/lib/components/admin-page/settings/ffmpeg/ffmpeg-settings.svelte b/web/src/lib/components/admin-page/settings/ffmpeg/ffmpeg-settings.svelte index d91df0325f..c78e6f72d6 100644 --- a/web/src/lib/components/admin-page/settings/ffmpeg/ffmpeg-settings.svelte +++ b/web/src/lib/components/admin-page/settings/ffmpeg/ffmpeg-settings.svelte @@ -143,7 +143,8 @@ { value: '1440', text: '1440p' }, { value: '1080', text: '1080p' }, { value: '720', text: '720p' }, - { value: '480', text: '480p' } + { value: '480', text: '480p' }, + { value: 'original', text: 'original' } ]} name="resolution" isEdited={!(ffmpegConfig.targetResolution == savedConfig.targetResolution)}