chore(server,cli,web): housekeeping and stricter code style (#6751)

* add unicorn to eslint

* fix lint errors for cli

* fix merge

* fix album name extraction

* Update cli/src/commands/upload.command.ts

Co-authored-by: Ben McCann <322311+benmccann@users.noreply.github.com>

* es2k23

* use lowercase os

* return undefined album name

* fix bug in asset response dto

* auto fix issues

* fix server code style

* es2022 and formatting

* fix compilation error

* fix test

* fix config load

* fix last lint errors

* set string type

* bump ts

* start work on web

* web formatting

* Fix UUIDParamDto as UUIDParamDto

* fix library service lint

* fix web errors

* fix errors

* formatting

* wip

* lints fixed

* web can now start

* alphabetical package json

* rename error

* chore: clean up

---------

Co-authored-by: Ben McCann <322311+benmccann@users.noreply.github.com>
Co-authored-by: Jason Rasmussen <jrasm91@gmail.com>
This commit is contained in:
Jonathan Jogenfors
2024-02-02 04:18:00 +01:00
committed by GitHub
parent e4d0560d49
commit f44fa45aa0
218 changed files with 2471 additions and 1244 deletions
+42 -24
View File
@@ -181,13 +181,14 @@ export class MediaService {
this.storageCore.ensureFolders(path);
switch (asset.type) {
case AssetType.IMAGE:
case AssetType.IMAGE: {
const colorspace = this.isSRGB(asset) ? Colorspace.SRGB : thumbnail.colorspace;
const thumbnailOptions = { format, size, colorspace, quality: thumbnail.quality };
await this.mediaRepository.resize(asset.originalPath, path, thumbnailOptions);
break;
}
case AssetType.VIDEO:
case AssetType.VIDEO: {
const { audioStreams, videoStreams } = await this.mediaRepository.probe(asset.originalPath);
const mainVideoStream = this.getMainStream(videoStreams);
if (!mainVideoStream) {
@@ -199,9 +200,11 @@ export class MediaService {
const options = new ThumbnailConfig(config).getOptions(mainVideoStream, mainAudioStream);
await this.mediaRepository.transcode(asset.originalPath, path, options);
break;
}
default:
default: {
throw new UnsupportedMediaTypeException(`Unsupported asset type for thumbnail generation: ${asset.type}`);
}
}
this.logger.log(
`Successfully generated ${format.toUpperCase()} ${asset.type.toLowerCase()} thumbnail for asset ${asset.id}`,
@@ -297,16 +300,16 @@ export class MediaService {
let transcodeOptions;
try {
transcodeOptions = await this.getCodecConfig(config).then((c) => c.getOptions(mainVideoStream, mainAudioStream));
} catch (err) {
this.logger.error(`An error occurred while configuring transcoding options: ${err}`);
} catch (error) {
this.logger.error(`An error occurred while configuring transcoding options: ${error}`);
return false;
}
this.logger.log(`Start encoding video ${asset.id} ${JSON.stringify(transcodeOptions)}`);
try {
await this.mediaRepository.transcode(input, output, transcodeOptions);
} catch (err) {
this.logger.error(err);
} catch (error) {
this.logger.error(error);
if (config.accel !== TranscodeHWAccel.DISABLED) {
this.logger.error(
`Error occurred during transcoding. Retrying with ${config.accel.toUpperCase()} acceleration disabled.`,
@@ -354,23 +357,29 @@ export class MediaService {
const isLargerThanTargetBitrate = bitrate > this.parseBitrateToBps(ffmpegConfig.maxBitrate);
switch (ffmpegConfig.transcode) {
case TranscodePolicy.DISABLED:
case TranscodePolicy.DISABLED: {
return false;
}
case TranscodePolicy.ALL:
case TranscodePolicy.ALL: {
return true;
}
case TranscodePolicy.REQUIRED:
case TranscodePolicy.REQUIRED: {
return !allTargetsMatching || videoStream.isHDR;
}
case TranscodePolicy.OPTIMAL:
case TranscodePolicy.OPTIMAL: {
return !allTargetsMatching || isLargerThanTargetRes || videoStream.isHDR;
}
case TranscodePolicy.BITRATE:
case TranscodePolicy.BITRATE: {
return !allTargetsMatching || isLargerThanTargetBitrate || videoStream.isHDR;
}
default:
default: {
return false;
}
}
}
@@ -383,14 +392,18 @@ export class MediaService {
private getSWCodecConfig(config: SystemConfigFFmpegDto) {
switch (config.targetVideoCodec) {
case VideoCodec.H264:
case VideoCodec.H264: {
return new H264Config(config);
case VideoCodec.HEVC:
}
case VideoCodec.HEVC: {
return new HEVCConfig(config);
case VideoCodec.VP9:
}
case VideoCodec.VP9: {
return new VP9Config(config);
default:
}
default: {
throw new UnsupportedMediaTypeException(`Codec '${config.targetVideoCodec}' is unsupported`);
}
}
}
@@ -398,23 +411,28 @@ export class MediaService {
let handler: VideoCodecHWConfig;
let devices: string[];
switch (config.accel) {
case TranscodeHWAccel.NVENC:
case TranscodeHWAccel.NVENC: {
handler = new NVENCConfig(config);
break;
case TranscodeHWAccel.QSV:
}
case TranscodeHWAccel.QSV: {
devices = await this.storageRepository.readdir('/dev/dri');
handler = new QSVConfig(config, devices);
break;
case TranscodeHWAccel.VAAPI:
}
case TranscodeHWAccel.VAAPI: {
devices = await this.storageRepository.readdir('/dev/dri');
handler = new VAAPIConfig(config, devices);
break;
case TranscodeHWAccel.RKMPP:
}
case TranscodeHWAccel.RKMPP: {
devices = await this.storageRepository.readdir('/dev/dri');
handler = new RKMPPConfig(config, devices);
break;
default:
}
default: {
throw new UnsupportedMediaTypeException(`${config.accel.toUpperCase()} acceleration is unsupported`);
}
}
if (!handler.getSupportedCodecs().includes(config.targetVideoCodec)) {
throw new UnsupportedMediaTypeException(
@@ -441,14 +459,14 @@ export class MediaService {
parseBitrateToBps(bitrateString: string) {
const bitrateValue = Number.parseInt(bitrateString);
if (isNaN(bitrateValue)) {
if (Number.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
return bitrateValue * 1_000_000; // Megabits per second to bits per second
} else {
return bitrateValue;
}
+19 -21
View File
@@ -15,16 +15,14 @@ class BaseConfig implements VideoCodecSWConfig {
getOptions(videoStream: VideoStreamInfo, audioStream?: AudioStreamInfo) {
const options = {
inputOptions: this.getBaseInputOptions(),
outputOptions: this.getBaseOutputOptions(videoStream, audioStream).concat('-v verbose'),
outputOptions: [...this.getBaseOutputOptions(videoStream, audioStream), '-v verbose'],
twoPass: this.eligibleForTwoPass(),
} as TranscodeOptions;
const filters = this.getFilterOptions(videoStream);
if (filters.length > 0) {
options.outputOptions.push(`-vf ${filters.join(',')}`);
}
options.outputOptions.push(...this.getPresetOptions());
options.outputOptions.push(...this.getThreadOptions());
options.outputOptions.push(...this.getBitrateOptions());
options.outputOptions.push(...this.getPresetOptions(), ...this.getThreadOptions(), ...this.getBitrateOptions());
return options;
}
@@ -129,11 +127,10 @@ class BaseConfig implements VideoCodecSWConfig {
getTargetResolution(videoStream: VideoStreamInfo) {
let target;
if (this.config.targetResolution === 'original') {
target = Math.min(videoStream.height, videoStream.width);
} else {
target = Number.parseInt(this.config.targetResolution);
}
target =
this.config.targetResolution === 'original'
? Math.min(videoStream.height, videoStream.width)
: Number.parseInt(this.config.targetResolution);
if (target % 2 !== 0) {
target -= 1;
@@ -182,7 +179,7 @@ class BaseConfig implements VideoCodecSWConfig {
getBitrateUnit() {
const maxBitrate = this.getMaxBitrateValue();
return this.config.maxBitrate.trim().substring(maxBitrate.toString().length); // use inputted unit if provided
return this.config.maxBitrate.trim().slice(maxBitrate.toString().length); // use inputted unit if provided
}
getMaxBitrateValue() {
@@ -411,8 +408,7 @@ export class NVENCConfig extends BaseHWConfig {
...super.getBaseOutputOptions(videoStream, audioStream),
];
if (this.getBFrames() > 0) {
options.push('-b_ref_mode middle');
options.push('-b_qfactor 1.1');
options.push('-b_ref_mode middle', '-b_qfactor 1.1');
}
if (this.config.temporalAQ) {
options.push('-temporal-aq 1');
@@ -474,8 +470,8 @@ export class NVENCConfig extends BaseHWConfig {
export class QSVConfig extends BaseHWConfig {
getBaseInputOptions() {
if (!this.devices.length) {
throw Error('No QSV device found');
if (this.devices.length === 0) {
throw new Error('No QSV device found');
}
let qsvString = '';
@@ -519,8 +515,7 @@ export class QSVConfig extends BaseHWConfig {
options.push(`-${this.useCQP() ? 'q:v' : 'global_quality'} ${this.config.crf}`);
const bitrates = this.getBitrateDistribution();
if (bitrates.max > 0) {
options.push(`-maxrate ${bitrates.max}${bitrates.unit}`);
options.push(`-bufsize ${bitrates.max * 2}${bitrates.unit}`);
options.push(`-maxrate ${bitrates.max}${bitrates.unit}`, `-bufsize ${bitrates.max * 2}${bitrates.unit}`);
}
return options;
}
@@ -623,7 +618,7 @@ export class RKMPPConfig extends BaseHWConfig {
getBaseInputOptions() {
if (this.devices.length === 0) {
throw Error('No RKMPP device found');
throw new Error('No RKMPP device found');
}
return [];
}
@@ -642,14 +637,17 @@ export class RKMPPConfig extends BaseHWConfig {
getPresetOptions() {
switch (this.config.targetVideoCodec) {
case VideoCodec.H264:
case VideoCodec.H264: {
// from ffmpeg_mpp help, commonly referred to as H264 level 5.1
return ['-level 51'];
case VideoCodec.HEVC:
}
case VideoCodec.HEVC: {
// from ffmpeg_mpp help, commonly referred to as HEVC level 5.1
return ['-level 153'];
default:
throw Error(`Incompatible video codec for RKMPP: ${this.config.targetVideoCodec}`);
}
default: {
throw new Error(`Incompatible video codec for RKMPP: ${this.config.targetVideoCodec}`);
}
}
}