mirror of
https://github.com/immich-app/immich.git
synced 2024-11-15 09:59:00 -07:00
feat(server): easy RKMPP video encoding (#7460)
* feat(server): easy RKMPP video encoding * make linter happy
This commit is contained in:
parent
cfb49c8be0
commit
5e485e35e9
@ -38,12 +38,6 @@ services:
|
||||
- /dev/dri:/dev/dri
|
||||
- /dev/dma_heap:/dev/dma_heap
|
||||
- /dev/mpp_service:/dev/mpp_service
|
||||
volumes:
|
||||
- /usr/bin/ffmpeg:/usr/bin/ffmpeg_mpp:ro
|
||||
- /lib/aarch64-linux-gnu:/lib/ffmpeg-mpp:ro
|
||||
- /lib/aarch64-linux-gnu/libblas.so.3:/lib/ffmpeg-mpp/libblas.so.3:ro # symlink is resolved by mounting
|
||||
- /lib/aarch64-linux-gnu/liblapack.so.3:/lib/ffmpeg-mpp/liblapack.so.3:ro # symlink is resolved by mounting
|
||||
- /lib/aarch64-linux-gnu/pulseaudio/libpulsecommon-15.99.so:/lib/ffmpeg-mpp/libpulsecommon-15.99.so:ro
|
||||
|
||||
vaapi:
|
||||
devices:
|
||||
|
@ -1801,7 +1801,7 @@ describe(MediaService.name, () => {
|
||||
{
|
||||
inputOptions: [],
|
||||
outputOptions: [
|
||||
`-c:v hevc_rkmpp_encoder`,
|
||||
`-c:v hevc_rkmpp`,
|
||||
'-c:a copy',
|
||||
'-movflags faststart',
|
||||
'-fps_mode passthrough',
|
||||
@ -1810,17 +1810,12 @@ describe(MediaService.name, () => {
|
||||
'-g 256',
|
||||
'-tag:v hvc1',
|
||||
'-v verbose',
|
||||
'-vf scale=-2:720,format=yuv420p',
|
||||
'-level 153',
|
||||
'-rc_mode 3',
|
||||
'-quality_min 0',
|
||||
'-quality_max 100',
|
||||
'-b:v 10000k',
|
||||
'-width 1280',
|
||||
'-height 720',
|
||||
],
|
||||
twoPass: false,
|
||||
ffmpegPath: 'ffmpeg_mpp',
|
||||
ldLibraryPath: '/lib/aarch64-linux-gnu:/lib/ffmpeg-mpp',
|
||||
},
|
||||
);
|
||||
});
|
||||
@ -1841,7 +1836,7 @@ describe(MediaService.name, () => {
|
||||
{
|
||||
inputOptions: [],
|
||||
outputOptions: [
|
||||
`-c:v h264_rkmpp_encoder`,
|
||||
`-c:v h264_rkmpp`,
|
||||
'-c:a copy',
|
||||
'-movflags faststart',
|
||||
'-fps_mode passthrough',
|
||||
@ -1849,16 +1844,12 @@ describe(MediaService.name, () => {
|
||||
'-map 0:1',
|
||||
'-g 256',
|
||||
'-v verbose',
|
||||
'-vf scale=-2:720,format=yuv420p',
|
||||
'-level 51',
|
||||
'-rc_mode 2',
|
||||
'-quality_min 51',
|
||||
'-quality_max 51',
|
||||
'-width 1280',
|
||||
'-height 720',
|
||||
'-qp_init 30',
|
||||
],
|
||||
twoPass: false,
|
||||
ffmpegPath: 'ffmpeg_mpp',
|
||||
ldLibraryPath: '/lib/aarch64-linux-gnu:/lib/ffmpeg-mpp',
|
||||
},
|
||||
);
|
||||
});
|
||||
|
@ -607,16 +607,6 @@ export class VAAPIConfig extends BaseHWConfig {
|
||||
}
|
||||
|
||||
export class RKMPPConfig extends BaseHWConfig {
|
||||
getOptions(target: TranscodeTarget, videoStream: VideoStreamInfo, audioStream?: AudioStreamInfo): TranscodeOptions {
|
||||
const options = super.getOptions(target, videoStream, audioStream);
|
||||
options.ffmpegPath = 'ffmpeg_mpp';
|
||||
options.ldLibraryPath = '/lib/aarch64-linux-gnu:/lib/ffmpeg-mpp';
|
||||
if ([TranscodeTarget.ALL, TranscodeTarget.VIDEO].includes(target)) {
|
||||
options.outputOptions.push(...this.getSizeOptions(videoStream));
|
||||
}
|
||||
return options;
|
||||
}
|
||||
|
||||
eligibleForTwoPass(): boolean {
|
||||
return false;
|
||||
}
|
||||
@ -628,18 +618,6 @@ export class RKMPPConfig extends BaseHWConfig {
|
||||
return [];
|
||||
}
|
||||
|
||||
getFilterOptions(videoStream: VideoStreamInfo) {
|
||||
return this.shouldToneMap(videoStream) ? this.getToneMapping() : [];
|
||||
}
|
||||
|
||||
getSizeOptions(videoStream: VideoStreamInfo) {
|
||||
if (this.shouldScale(videoStream)) {
|
||||
const { width, height } = this.getSize(videoStream);
|
||||
return [`-width ${width}`, `-height ${height}`];
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
getPresetOptions() {
|
||||
switch (this.config.targetVideoCodec) {
|
||||
case VideoCodec.H264: {
|
||||
@ -659,12 +637,11 @@ export class RKMPPConfig extends BaseHWConfig {
|
||||
getBitrateOptions() {
|
||||
const bitrate = this.getMaxBitrateValue();
|
||||
if (bitrate > 0) {
|
||||
return ['-rc_mode 3', '-quality_min 0', '-quality_max 100', `-b:v ${bitrate}${this.getBitrateUnit()}`];
|
||||
} else {
|
||||
// convert CQP from 51-10 to 0-100, values below 10 are set to 10
|
||||
const quality = Math.floor(125 - Math.max(this.config.crf, 10) * (125 / 51));
|
||||
return ['-rc_mode 2', `-quality_min ${quality}`, `-quality_max ${quality}`];
|
||||
// -b:v specifies max bitrate, average bitrate is derived automatically...
|
||||
return ['-rc_mode 3', `-b:v ${bitrate}${this.getBitrateUnit()}`];
|
||||
}
|
||||
// use CRF value as QP value
|
||||
return ['-rc_mode 2', `-qp_init ${this.config.crf}`];
|
||||
}
|
||||
|
||||
getSupportedCodecs() {
|
||||
@ -672,6 +649,6 @@ export class RKMPPConfig extends BaseHWConfig {
|
||||
}
|
||||
|
||||
getVideoCodec(): string {
|
||||
return `${this.config.targetVideoCodec}_rkmpp_encoder`;
|
||||
return `${this.config.targetVideoCodec}_rkmpp`;
|
||||
}
|
||||
}
|
||||
|
@ -51,8 +51,6 @@ export interface TranscodeOptions {
|
||||
inputOptions: string[];
|
||||
outputOptions: string[];
|
||||
twoPass: boolean;
|
||||
ffmpegPath?: string;
|
||||
ldLibraryPath?: string;
|
||||
}
|
||||
|
||||
export interface BitrateDistribution {
|
||||
|
@ -76,18 +76,7 @@ export class MediaRepository implements IMediaRepository {
|
||||
transcode(input: string, output: string | Writable, options: TranscodeOptions): Promise<void> {
|
||||
if (!options.twoPass) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const oldLdLibraryPath = process.env.LD_LIBRARY_PATH;
|
||||
if (options.ldLibraryPath) {
|
||||
// fluent ffmpeg does not allow to set environment variables, so we do it manually
|
||||
process.env.LD_LIBRARY_PATH = this.chainPath(oldLdLibraryPath || '', options.ldLibraryPath);
|
||||
}
|
||||
try {
|
||||
this.configureFfmpegCall(input, output, options).on('error', reject).on('end', resolve).run();
|
||||
} finally {
|
||||
if (options.ldLibraryPath) {
|
||||
process.env.LD_LIBRARY_PATH = oldLdLibraryPath;
|
||||
}
|
||||
}
|
||||
this.configureFfmpegCall(input, output, options).on('error', reject).on('end', resolve).run();
|
||||
});
|
||||
}
|
||||
|
||||
@ -121,7 +110,6 @@ export class MediaRepository implements IMediaRepository {
|
||||
|
||||
configureFfmpegCall(input: string, output: string | Writable, options: TranscodeOptions) {
|
||||
return ffmpeg(input, { niceness: 10 })
|
||||
.setFfmpegPath(options.ffmpegPath || 'ffmpeg')
|
||||
.inputOptions(options.inputOptions)
|
||||
.outputOptions(options.outputOptions)
|
||||
.output(output)
|
||||
|
Loading…
Reference in New Issue
Block a user