1
0
mirror of https://github.com/immich-app/immich.git synced 2025-07-06 06:07:29 +02: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:
Mert
2023-09-02 21:22:42 -04:00
committed by GitHub
parent 67ac686704
commit f8ff342852
24 changed files with 797 additions and 188 deletions

88
mobile/openapi/lib/model/cq_mode.dart generated Normal file
View File

@ -0,0 +1,88 @@
//
// AUTO-GENERATED FILE, DO NOT MODIFY!
//
// @dart=2.12
// ignore_for_file: unused_element, unused_import
// ignore_for_file: always_put_required_named_parameters_first
// ignore_for_file: constant_identifier_names
// ignore_for_file: lines_longer_than_80_chars
part of openapi.api;
class CQMode {
/// Instantiate a new enum with the provided [value].
const CQMode._(this.value);
/// The underlying value of this enum member.
final String value;
@override
String toString() => value;
String toJson() => value;
static const auto = CQMode._(r'auto');
static const cqp = CQMode._(r'cqp');
static const icq = CQMode._(r'icq');
/// List of all possible values in this [enum][CQMode].
static const values = <CQMode>[
auto,
cqp,
icq,
];
static CQMode? fromJson(dynamic value) => CQModeTypeTransformer().decode(value);
static List<CQMode>? listFromJson(dynamic json, {bool growable = false,}) {
final result = <CQMode>[];
if (json is List && json.isNotEmpty) {
for (final row in json) {
final value = CQMode.fromJson(row);
if (value != null) {
result.add(value);
}
}
}
return result.toList(growable: growable);
}
}
/// Transformation class that can [encode] an instance of [CQMode] to String,
/// and [decode] dynamic data back to [CQMode].
class CQModeTypeTransformer {
factory CQModeTypeTransformer() => _instance ??= const CQModeTypeTransformer._();
const CQModeTypeTransformer._();
String encode(CQMode data) => data.value;
/// Decodes a [dynamic value][data] to a CQMode.
///
/// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully,
/// then null is returned. However, if [allowNull] is false and the [dynamic value][data]
/// cannot be decoded successfully, then an [UnimplementedError] is thrown.
///
/// The [allowNull] is very handy when an API changes and a new enum value is added or removed,
/// and users are still using an old app with the old code.
CQMode? decode(dynamic data, {bool allowNull = true}) {
if (data != null) {
switch (data) {
case r'auto': return CQMode.auto;
case r'cqp': return CQMode.cqp;
case r'icq': return CQMode.icq;
default:
if (!allowNull) {
throw ArgumentError('Unknown enum value to decode: $data');
}
}
}
return null;
}
/// Singleton [CQModeTypeTransformer] instance.
static CQModeTypeTransformer? _instance;
}

View File

@ -14,12 +14,18 @@ class SystemConfigFFmpegDto {
/// Returns a new [SystemConfigFFmpegDto] instance.
SystemConfigFFmpegDto({
required this.accel,
required this.bframes,
required this.cqMode,
required this.crf,
required this.gopSize,
required this.maxBitrate,
required this.npl,
required this.preset,
required this.refs,
required this.targetAudioCodec,
required this.targetResolution,
required this.targetVideoCodec,
required this.temporalAQ,
required this.threads,
required this.tonemap,
required this.transcode,
@ -28,18 +34,30 @@ class SystemConfigFFmpegDto {
TranscodeHWAccel accel;
int bframes;
CQMode cqMode;
int crf;
int gopSize;
String maxBitrate;
int npl;
String preset;
int refs;
AudioCodec targetAudioCodec;
String targetResolution;
VideoCodec targetVideoCodec;
bool temporalAQ;
int threads;
ToneMapping tonemap;
@ -51,12 +69,18 @@ class SystemConfigFFmpegDto {
@override
bool operator ==(Object other) => identical(this, other) || other is SystemConfigFFmpegDto &&
other.accel == accel &&
other.bframes == bframes &&
other.cqMode == cqMode &&
other.crf == crf &&
other.gopSize == gopSize &&
other.maxBitrate == maxBitrate &&
other.npl == npl &&
other.preset == preset &&
other.refs == refs &&
other.targetAudioCodec == targetAudioCodec &&
other.targetResolution == targetResolution &&
other.targetVideoCodec == targetVideoCodec &&
other.temporalAQ == temporalAQ &&
other.threads == threads &&
other.tonemap == tonemap &&
other.transcode == transcode &&
@ -66,29 +90,41 @@ class SystemConfigFFmpegDto {
int get hashCode =>
// ignore: unnecessary_parenthesis
(accel.hashCode) +
(bframes.hashCode) +
(cqMode.hashCode) +
(crf.hashCode) +
(gopSize.hashCode) +
(maxBitrate.hashCode) +
(npl.hashCode) +
(preset.hashCode) +
(refs.hashCode) +
(targetAudioCodec.hashCode) +
(targetResolution.hashCode) +
(targetVideoCodec.hashCode) +
(temporalAQ.hashCode) +
(threads.hashCode) +
(tonemap.hashCode) +
(transcode.hashCode) +
(twoPass.hashCode);
@override
String toString() => 'SystemConfigFFmpegDto[accel=$accel, crf=$crf, maxBitrate=$maxBitrate, preset=$preset, targetAudioCodec=$targetAudioCodec, targetResolution=$targetResolution, targetVideoCodec=$targetVideoCodec, threads=$threads, tonemap=$tonemap, transcode=$transcode, twoPass=$twoPass]';
String toString() => 'SystemConfigFFmpegDto[accel=$accel, bframes=$bframes, cqMode=$cqMode, crf=$crf, gopSize=$gopSize, maxBitrate=$maxBitrate, npl=$npl, preset=$preset, refs=$refs, targetAudioCodec=$targetAudioCodec, targetResolution=$targetResolution, targetVideoCodec=$targetVideoCodec, temporalAQ=$temporalAQ, threads=$threads, tonemap=$tonemap, transcode=$transcode, twoPass=$twoPass]';
Map<String, dynamic> toJson() {
final json = <String, dynamic>{};
json[r'accel'] = this.accel;
json[r'bframes'] = this.bframes;
json[r'cqMode'] = this.cqMode;
json[r'crf'] = this.crf;
json[r'gopSize'] = this.gopSize;
json[r'maxBitrate'] = this.maxBitrate;
json[r'npl'] = this.npl;
json[r'preset'] = this.preset;
json[r'refs'] = this.refs;
json[r'targetAudioCodec'] = this.targetAudioCodec;
json[r'targetResolution'] = this.targetResolution;
json[r'targetVideoCodec'] = this.targetVideoCodec;
json[r'temporalAQ'] = this.temporalAQ;
json[r'threads'] = this.threads;
json[r'tonemap'] = this.tonemap;
json[r'transcode'] = this.transcode;
@ -105,12 +141,18 @@ class SystemConfigFFmpegDto {
return SystemConfigFFmpegDto(
accel: TranscodeHWAccel.fromJson(json[r'accel'])!,
bframes: mapValueOfType<int>(json, r'bframes')!,
cqMode: CQMode.fromJson(json[r'cqMode'])!,
crf: mapValueOfType<int>(json, r'crf')!,
gopSize: mapValueOfType<int>(json, r'gopSize')!,
maxBitrate: mapValueOfType<String>(json, r'maxBitrate')!,
npl: mapValueOfType<int>(json, r'npl')!,
preset: mapValueOfType<String>(json, r'preset')!,
refs: mapValueOfType<int>(json, r'refs')!,
targetAudioCodec: AudioCodec.fromJson(json[r'targetAudioCodec'])!,
targetResolution: mapValueOfType<String>(json, r'targetResolution')!,
targetVideoCodec: VideoCodec.fromJson(json[r'targetVideoCodec'])!,
temporalAQ: mapValueOfType<bool>(json, r'temporalAQ')!,
threads: mapValueOfType<int>(json, r'threads')!,
tonemap: ToneMapping.fromJson(json[r'tonemap'])!,
transcode: TranscodePolicy.fromJson(json[r'transcode'])!,
@ -163,12 +205,18 @@ class SystemConfigFFmpegDto {
/// The list of required keys that must be present in a JSON.
static const requiredKeys = <String>{
'accel',
'bframes',
'cqMode',
'crf',
'gopSize',
'maxBitrate',
'npl',
'preset',
'refs',
'targetAudioCodec',
'targetResolution',
'targetVideoCodec',
'temporalAQ',
'threads',
'tonemap',
'transcode',