diff --git a/app/support/media-files/detect.ts b/app/support/media-files/detect.ts index 4c943156..a0e3cc90 100644 --- a/app/support/media-files/detect.ts +++ b/app/support/media-files/detect.ts @@ -99,6 +99,7 @@ export async function detectMediaType( vCodec: videoStream.codec_name, aCodec: audioStream?.codec_name, duration: parseFloat(format.duration), + bitrate: parseInt(format.bit_rate), width, height, h264info, @@ -146,6 +147,7 @@ async function detectAnimatedImage( width: videoStream.width!, height: videoStream.height!, duration: parseFloat(format.duration), + bitrate: parseInt(format.bit_rate), isAnimatedImage: true, }; } diff --git a/app/support/media-files/process.ts b/app/support/media-files/process.ts index 654a6b21..bfd6a1f4 100644 --- a/app/support/media-files/process.ts +++ b/app/support/media-files/process.ts @@ -358,6 +358,9 @@ async function processVideo( stillFile, ); + // Bitrate per pixel of the original video + const originalBpp = info.bitrate / (info.width * info.height); + for (const { variant, width, height } of previewSizes) { if (variant === maxVariant) { if (!canUseOriginalVideo) { @@ -384,13 +387,17 @@ async function processVideo( targetFile, ); } else { + const bitrateK = Math.round((1.5 * (originalBpp * (width * height))) / 1000); commands.push( ['-map', `[${variant}out]`], ['-c:v', 'libx264'], ['-preset', 'slow'], ['-profile:v', 'high'], ['-crf', '23'], - ['-g', '60'], // For better seeking performance + // For better seeking performance + ['-g', '60'], + // Limit the maximum bitrate + info.isAnimatedImage ? [] : ['-maxrate', `${bitrateK}k`, '-bufsize', `${2 * bitrateK}k`], ['-pix_fmt', 'yuv420p'], ...commonCommands, targetFile, diff --git a/app/support/media-files/types.ts b/app/support/media-files/types.ts index c3d4c0d3..1c89f221 100644 --- a/app/support/media-files/types.ts +++ b/app/support/media-files/types.ts @@ -33,6 +33,7 @@ export type MediaInfoVideo = { aCodec?: string; isAnimatedImage?: true; h264info?: H264Info; + bitrate: number; } & MediaInfoVisual & MediaInfoPlayable & MediaInfoCommon; @@ -109,7 +110,12 @@ export type AvcStream = Stream & { }; export type FfprobeResult = { - format: { format_name: string; duration: string; tags?: Record }; + format: { + format_name: string; + duration: string; + bit_rate: string; + tags?: Record; + }; streams: Stream[]; }; diff --git a/test/fixtures/media-files/file-info.json b/test/fixtures/media-files/file-info.json index ea3cd999..8c7725b9 100644 --- a/test/fixtures/media-files/file-info.json +++ b/test/fixtures/media-files/file-info.json @@ -9,7 +9,8 @@ "height": 256, "duration": 7.6, "isAnimatedImage": true, - "extension": "gif" + "extension": "gif", + "bitrate": 391272 } }, { @@ -77,6 +78,7 @@ "width": 1280, "height": 720, "duration": 5.005, + "bitrate": 1711589, "tags": { "title": "Kreuz-Polka", "major_brand": "isom", @@ -98,6 +100,7 @@ "width": 1280, "height": 720, "duration": 4.993, + "bitrate": 2942024, "extension": "ogv" } }, @@ -111,6 +114,7 @@ "width": 1280, "height": 720, "duration": 5.237, + "bitrate": 1472789, "tags": { "encoder": "Lavf58.29.100" }, "extension": "wmv"