mirror of
https://github.com/KevinMidboe/immich.git
synced 2025-10-29 17:40:28 +00:00
feat(server): advanced settings for transcoding (#3775)
* set stream with `-map` flag * updated tests * fixed audio stream mapping * added bframe setting to config * updated api * added b-frame option in dashboard * updated tests and formatting * "Advanced" section for FFmpeg with extra options * updated api * updated tests and formatting * styling * made vp9 bitstream filters conditional on b-frames * fixed gop size condition * add cq override * simplified isEdited conditions * simplified conditional flow for cq mode * fixed dto * clarified cq mode in description * formatting * added npl setting * Adjusted b-frame title and description * fixed rebase * changed defaults for pascal compatibility, added temporal aq setting * updated api * added temporal aq to ui * polished dashboard * formatting
This commit is contained in:
51
web/src/api/open-api/api.ts
generated
51
web/src/api/open-api/api.ts
generated
@@ -909,6 +909,21 @@ export const CLIPMode = {
|
||||
export type CLIPMode = typeof CLIPMode[keyof typeof CLIPMode];
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @export
|
||||
* @enum {string}
|
||||
*/
|
||||
|
||||
export const CQMode = {
|
||||
Auto: 'auto',
|
||||
Cqp: 'cqp',
|
||||
Icq: 'icq'
|
||||
} as const;
|
||||
|
||||
export type CQMode = typeof CQMode[keyof typeof CQMode];
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @export
|
||||
@@ -2812,24 +2827,54 @@ export interface SystemConfigFFmpegDto {
|
||||
* @memberof SystemConfigFFmpegDto
|
||||
*/
|
||||
'accel': TranscodeHWAccel;
|
||||
/**
|
||||
*
|
||||
* @type {number}
|
||||
* @memberof SystemConfigFFmpegDto
|
||||
*/
|
||||
'bframes': number;
|
||||
/**
|
||||
*
|
||||
* @type {CQMode}
|
||||
* @memberof SystemConfigFFmpegDto
|
||||
*/
|
||||
'cqMode': CQMode;
|
||||
/**
|
||||
*
|
||||
* @type {number}
|
||||
* @memberof SystemConfigFFmpegDto
|
||||
*/
|
||||
'crf': number;
|
||||
/**
|
||||
*
|
||||
* @type {number}
|
||||
* @memberof SystemConfigFFmpegDto
|
||||
*/
|
||||
'gopSize': number;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof SystemConfigFFmpegDto
|
||||
*/
|
||||
'maxBitrate': string;
|
||||
/**
|
||||
*
|
||||
* @type {number}
|
||||
* @memberof SystemConfigFFmpegDto
|
||||
*/
|
||||
'npl': number;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof SystemConfigFFmpegDto
|
||||
*/
|
||||
'preset': string;
|
||||
/**
|
||||
*
|
||||
* @type {number}
|
||||
* @memberof SystemConfigFFmpegDto
|
||||
*/
|
||||
'refs': number;
|
||||
/**
|
||||
*
|
||||
* @type {AudioCodec}
|
||||
@@ -2848,6 +2893,12 @@ export interface SystemConfigFFmpegDto {
|
||||
* @memberof SystemConfigFFmpegDto
|
||||
*/
|
||||
'targetVideoCodec': VideoCodec;
|
||||
/**
|
||||
*
|
||||
* @type {boolean}
|
||||
* @memberof SystemConfigFFmpegDto
|
||||
*/
|
||||
'temporalAQ': boolean;
|
||||
/**
|
||||
*
|
||||
* @type {number}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
import {
|
||||
api,
|
||||
AudioCodec,
|
||||
CQMode,
|
||||
SystemConfigFFmpegDto,
|
||||
ToneMapping,
|
||||
TranscodeHWAccel,
|
||||
@@ -19,6 +20,7 @@
|
||||
import HelpCircleOutline from 'svelte-material-icons/HelpCircleOutline.svelte';
|
||||
import { isEqual } from 'lodash-es';
|
||||
import { fade } from 'svelte/transition';
|
||||
import SettingAccordion from '../setting-accordion.svelte';
|
||||
|
||||
export let ffmpegConfig: SystemConfigFFmpegDto; // this is the config that is being edited
|
||||
export let disabled = false;
|
||||
@@ -112,7 +114,7 @@
|
||||
desc="Video quality level. Typical values are 23 for H.264, 28 for HEVC, and 31 for VP9. Lower is better, but takes longer to encode and produces larger files."
|
||||
bind:value={ffmpegConfig.crf}
|
||||
required={true}
|
||||
isEdited={!(ffmpegConfig.crf == savedConfig.crf)}
|
||||
isEdited={ffmpegConfig.crf !== savedConfig.crf}
|
||||
/>
|
||||
|
||||
<SettingSelect
|
||||
@@ -132,7 +134,7 @@
|
||||
{ value: 'slower', text: 'slower' },
|
||||
{ value: 'veryslow', text: 'veryslow' },
|
||||
]}
|
||||
isEdited={!(ffmpegConfig.preset == savedConfig.preset)}
|
||||
isEdited={ffmpegConfig.preset !== savedConfig.preset}
|
||||
/>
|
||||
|
||||
<SettingSelect
|
||||
@@ -146,7 +148,7 @@
|
||||
{ value: AudioCodec.Opus, text: 'opus' },
|
||||
]}
|
||||
name="acodec"
|
||||
isEdited={!(ffmpegConfig.targetAudioCodec == savedConfig.targetAudioCodec)}
|
||||
isEdited={ffmpegConfig.targetAudioCodec !== savedConfig.targetAudioCodec}
|
||||
/>
|
||||
|
||||
<SettingSelect
|
||||
@@ -160,7 +162,7 @@
|
||||
{ value: VideoCodec.Vp9, text: 'vp9' },
|
||||
]}
|
||||
name="vcodec"
|
||||
isEdited={!(ffmpegConfig.targetVideoCodec == savedConfig.targetVideoCodec)}
|
||||
isEdited={ffmpegConfig.targetVideoCodec !== savedConfig.targetVideoCodec}
|
||||
/>
|
||||
|
||||
<SettingSelect
|
||||
@@ -177,7 +179,7 @@
|
||||
{ value: 'original', text: 'original' },
|
||||
]}
|
||||
name="resolution"
|
||||
isEdited={!(ffmpegConfig.targetResolution == savedConfig.targetResolution)}
|
||||
isEdited={ffmpegConfig.targetResolution !== savedConfig.targetResolution}
|
||||
/>
|
||||
|
||||
<SettingInputField
|
||||
@@ -186,7 +188,7 @@
|
||||
label="MAX BITRATE"
|
||||
desc="Setting a max bitrate can make file sizes more predictable at a minor cost to quality. At 720p, typical values are 2600k for VP9 or HEVC, or 4500k for H.264. Disabled if set to 0."
|
||||
bind:value={ffmpegConfig.maxBitrate}
|
||||
isEdited={!(ffmpegConfig.maxBitrate == savedConfig.maxBitrate)}
|
||||
isEdited={ffmpegConfig.maxBitrate !== savedConfig.maxBitrate}
|
||||
/>
|
||||
|
||||
<SettingInputField
|
||||
@@ -195,7 +197,7 @@
|
||||
label="THREADS"
|
||||
desc="Higher values lead to faster encoding, but leave less room for the server to process other tasks while active. This value should not be more than the number of CPU cores. Maximizes utilization if set to 0."
|
||||
bind:value={ffmpegConfig.threads}
|
||||
isEdited={!(ffmpegConfig.threads == savedConfig.threads)}
|
||||
isEdited={ffmpegConfig.threads !== savedConfig.threads}
|
||||
/>
|
||||
|
||||
<SettingSelect
|
||||
@@ -219,31 +221,7 @@
|
||||
text: "Don't transcode any videos, may break playback on some clients",
|
||||
},
|
||||
]}
|
||||
isEdited={!(ffmpegConfig.transcode == savedConfig.transcode)}
|
||||
/>
|
||||
|
||||
<SettingSelect
|
||||
label="HARDWARE ACCELERATION"
|
||||
{disabled}
|
||||
desc="Experimental. Much faster, but will have lower quality at the same bitrate. This setting is 'best effort': it will fallback to software transcoding on failure. VP9 may or may not work depending on your hardware."
|
||||
bind:value={ffmpegConfig.accel}
|
||||
name="accel"
|
||||
options={[
|
||||
{ value: TranscodeHWAccel.Nvenc, text: 'NVENC (requires NVIDIA GPU)' },
|
||||
{
|
||||
value: TranscodeHWAccel.Qsv,
|
||||
text: 'Quick Sync (requires 7th gen Intel CPU or later)',
|
||||
},
|
||||
{
|
||||
value: TranscodeHWAccel.Vaapi,
|
||||
text: 'VAAPI',
|
||||
},
|
||||
{
|
||||
value: TranscodeHWAccel.Disabled,
|
||||
text: 'Disabled',
|
||||
},
|
||||
]}
|
||||
isEdited={!(ffmpegConfig.accel == savedConfig.accel)}
|
||||
isEdited={ffmpegConfig.transcode !== savedConfig.transcode}
|
||||
/>
|
||||
|
||||
<SettingSelect
|
||||
@@ -270,7 +248,7 @@
|
||||
text: 'Disabled',
|
||||
},
|
||||
]}
|
||||
isEdited={!(ffmpegConfig.tonemap == savedConfig.tonemap)}
|
||||
isEdited={ffmpegConfig.tonemap !== savedConfig.tonemap}
|
||||
/>
|
||||
|
||||
<SettingSwitch
|
||||
@@ -278,8 +256,95 @@
|
||||
{disabled}
|
||||
subtitle="Transcode in two passes to produce better encoded videos. When max bitrate is enabled (required for it to work with H.264 and HEVC), this mode uses a bitrate range based on the max bitrate and ignores CRF. For VP9, CRF can be used if max bitrate is disabled."
|
||||
bind:checked={ffmpegConfig.twoPass}
|
||||
isEdited={!(ffmpegConfig.twoPass === savedConfig.twoPass)}
|
||||
isEdited={ffmpegConfig.twoPass !== savedConfig.twoPass}
|
||||
/>
|
||||
|
||||
<SettingAccordion
|
||||
title="Hardware Acceleration"
|
||||
subtitle="Experimental; much faster, but will have lower quality at the same bitrate"
|
||||
>
|
||||
<div class="ml-4 mt-4 flex flex-col gap-4">
|
||||
<SettingSelect
|
||||
label="ACCELERATION API"
|
||||
{disabled}
|
||||
desc="The API that will interact with your device to accelerate transcoding. This setting is 'best effort': it will fallback to software transcoding on failure. VP9 may or may not work depending on your hardware."
|
||||
bind:value={ffmpegConfig.accel}
|
||||
name="accel"
|
||||
options={[
|
||||
{ value: TranscodeHWAccel.Nvenc, text: 'NVENC (requires NVIDIA GPU)' },
|
||||
{
|
||||
value: TranscodeHWAccel.Qsv,
|
||||
text: 'Quick Sync (requires 7th gen Intel CPU or later)',
|
||||
},
|
||||
{
|
||||
value: TranscodeHWAccel.Vaapi,
|
||||
text: 'VAAPI',
|
||||
},
|
||||
{
|
||||
value: TranscodeHWAccel.Disabled,
|
||||
text: 'Disabled',
|
||||
},
|
||||
]}
|
||||
isEdited={ffmpegConfig.accel !== savedConfig.accel}
|
||||
/>
|
||||
|
||||
<SettingSelect
|
||||
label="CONSTANT QUALITY MODE"
|
||||
desc="ICQ is better than CQP, but some hardware acceleration devices do not support this mode. Setting this option will prefer the specified mode when using quality-based encoding. Ignored by NVENC as it does not support ICQ."
|
||||
bind:value={ffmpegConfig.cqMode}
|
||||
options={[
|
||||
{ value: CQMode.Auto, text: 'Auto' },
|
||||
{ value: CQMode.Icq, text: 'ICQ' },
|
||||
{ value: CQMode.Cqp, text: 'CQP' },
|
||||
]}
|
||||
isEdited={ffmpegConfig.cqMode !== savedConfig.cqMode}
|
||||
/>
|
||||
|
||||
<SettingSwitch
|
||||
title="TEMPORAL AQ"
|
||||
{disabled}
|
||||
subtitle="Applies only to NVENC. Increases quality of high-detail, low-motion scenes. May not be compatible with older devices."
|
||||
bind:checked={ffmpegConfig.temporalAQ}
|
||||
isEdited={ffmpegConfig.temporalAQ !== savedConfig.temporalAQ}
|
||||
/>
|
||||
</div>
|
||||
</SettingAccordion>
|
||||
|
||||
<SettingAccordion title="Advanced" subtitle="Options most users should not need to change">
|
||||
<div class="ml-4 mt-4 flex flex-col gap-4">
|
||||
<SettingInputField
|
||||
inputType={SettingInputFieldType.NUMBER}
|
||||
label="TONE-MAPPING NPL"
|
||||
desc="Colors will be adjusted to look normal for a display of this brightness. Counter-intuitively, lower values increase the brightness of the video and vice versa since it compensates for the brightness of the display. 0 sets this value automatically."
|
||||
bind:value={ffmpegConfig.npl}
|
||||
isEdited={ffmpegConfig.npl !== savedConfig.npl}
|
||||
/>
|
||||
|
||||
<SettingInputField
|
||||
inputType={SettingInputFieldType.NUMBER}
|
||||
label="MAX B-FRAMES"
|
||||
desc="Higher values improve compression efficiency, but slow down encoding. May not be compatible with hardware acceleration on older devices. 0 disables B-frames, while -1 sets this value automatically."
|
||||
bind:value={ffmpegConfig.bframes}
|
||||
isEdited={ffmpegConfig.bframes !== savedConfig.bframes}
|
||||
/>
|
||||
|
||||
<SettingInputField
|
||||
inputType={SettingInputFieldType.NUMBER}
|
||||
label="REFERENCE FRAMES"
|
||||
desc="The number of frames to reference when compressing a given frame. Higher values improve compression efficiency, but slow down encoding. 0 sets this value automatically."
|
||||
bind:value={ffmpegConfig.refs}
|
||||
isEdited={ffmpegConfig.refs !== savedConfig.refs}
|
||||
/>
|
||||
|
||||
<SettingInputField
|
||||
inputType={SettingInputFieldType.NUMBER}
|
||||
label="MAX KEYFRAME INTERVAL"
|
||||
desc="Sets the maximum frame distance between keyframes. Lower values worsen compression efficiency, but improve seek times and may improve quality in scenes with fast movement. 0 sets this value automatically."
|
||||
bind:value={ffmpegConfig.gopSize}
|
||||
isEdited={ffmpegConfig.gopSize !== savedConfig.gopSize}
|
||||
/>
|
||||
</div>
|
||||
</SettingAccordion>
|
||||
</div>
|
||||
|
||||
<div class="ml-4">
|
||||
|
||||
@@ -13,8 +13,8 @@
|
||||
|
||||
export let inputType: SettingInputFieldType;
|
||||
export let value: string | number;
|
||||
export let min = Number.MIN_VALUE.toString();
|
||||
export let max = Number.MAX_VALUE.toString();
|
||||
export let min = Number.MIN_SAFE_INTEGER.toString();
|
||||
export let max = Number.MAX_SAFE_INTEGER.toString();
|
||||
export let step = '1';
|
||||
export let label = '';
|
||||
export let desc = '';
|
||||
|
||||
Reference in New Issue
Block a user