mirror of
https://github.com/Art051/immich.git
synced 2025-08-11 19:29:00 +00:00
feat(server, web): Added TranscodePolicy "Bitrate higher than max bitrate or not in accepted format" (#6479)
* chore: rebase * chore: open api * Add Database-Migration for setting targetCodec as acceptedCodec if it was set by admin * Add TranscodePolicy setting, to only transcode files with a bitrate higher than set max bitrate * Rename enum value of TranscodePolicy * calculate max_bitrate according to "k" and "m" suffix for comparison * remove migration * minor changes * UnitTest for Bitrate Policy * Fix UnitTest * Add missing output options --------- Co-authored-by: Jason Rasmussen <jrasm91@gmail.com> Co-authored-by: mertalev <101130780+mertalev@users.noreply.github.com>
This commit is contained in:
@@ -264,6 +264,7 @@ export class MediaService {
|
||||
const mainVideoStream = this.getMainStream(videoStreams);
|
||||
const mainAudioStream = this.getMainStream(audioStreams);
|
||||
const containerExtension = format.formatName;
|
||||
const bitrate = format.bitrate;
|
||||
if (!mainVideoStream || !containerExtension) {
|
||||
return false;
|
||||
}
|
||||
@@ -275,7 +276,14 @@ export class MediaService {
|
||||
|
||||
const { ffmpeg: config } = await this.configCore.getConfig();
|
||||
|
||||
const required = this.isTranscodeRequired(asset, mainVideoStream, mainAudioStream, containerExtension, config);
|
||||
const required = this.isTranscodeRequired(
|
||||
asset,
|
||||
mainVideoStream,
|
||||
mainAudioStream,
|
||||
containerExtension,
|
||||
config,
|
||||
bitrate,
|
||||
);
|
||||
if (!required) {
|
||||
if (asset.encodedVideoPath) {
|
||||
this.logger.log(`Transcoded video exists for asset ${asset.id}, but is no longer required. Deleting...`);
|
||||
@@ -326,6 +334,7 @@ export class MediaService {
|
||||
audioStream: AudioStreamInfo | null,
|
||||
containerExtension: string,
|
||||
ffmpegConfig: SystemConfigFFmpegDto,
|
||||
bitrate: number,
|
||||
): boolean {
|
||||
const isTargetVideoCodec = ffmpegConfig.acceptedVideoCodecs.includes(videoStream.codecName as VideoCodec);
|
||||
const isTargetContainer = ['mov,mp4,m4a,3gp,3g2,mj2', 'mp4', 'mov'].includes(containerExtension);
|
||||
@@ -342,6 +351,7 @@ export class MediaService {
|
||||
const scalingEnabled = ffmpegConfig.targetResolution !== 'original';
|
||||
const targetRes = Number.parseInt(ffmpegConfig.targetResolution);
|
||||
const isLargerThanTargetRes = scalingEnabled && Math.min(videoStream.height, videoStream.width) > targetRes;
|
||||
const isLargerThanTargetBitrate = bitrate > this.parseBitrateToBps(ffmpegConfig.maxBitrate);
|
||||
|
||||
switch (ffmpegConfig.transcode) {
|
||||
case TranscodePolicy.DISABLED:
|
||||
@@ -356,6 +366,9 @@ export class MediaService {
|
||||
case TranscodePolicy.OPTIMAL:
|
||||
return !allTargetsMatching || isLargerThanTargetRes || videoStream.isHDR;
|
||||
|
||||
case TranscodePolicy.BITRATE:
|
||||
return !allTargetsMatching || isLargerThanTargetBitrate || videoStream.isHDR;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@@ -424,4 +437,20 @@ export class MediaService {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
parseBitrateToBps(bitrateString: string) {
|
||||
const bitrateValue = Number.parseInt(bitrateString);
|
||||
|
||||
if (isNaN(bitrateValue)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (bitrateString.toLowerCase().endsWith('k')) {
|
||||
return bitrateValue * 1000; // Kilobits per second to bits per second
|
||||
} else if (bitrateString.toLowerCase().endsWith('m')) {
|
||||
return bitrateValue * 1000000; // Megabits per second to bits per second
|
||||
} else {
|
||||
return bitrateValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user