1
0
mirror of https://github.com/immich-app/immich.git synced 2024-11-24 08:52:28 +02:00

perf: cache transcoding devices (#9381)

cache transcoding devices
This commit is contained in:
Mert 2024-05-10 15:03:47 -04:00 committed by GitHub
parent f3fbb9b588
commit bb4843747b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 35 additions and 21 deletions

View File

@ -2053,14 +2053,19 @@ describe(MediaService.name, () => {
twoPass: false, twoPass: false,
}, },
); );
});
storageMock.readdir.mockResolvedValue(['renderD129', 'renderD128']); it('should prefer higher index gpu node', async () => {
storageMock.readdir.mockResolvedValue(['renderD129', 'renderD130', 'renderD128']);
mediaMock.probe.mockResolvedValue(probeStub.matroskaContainer);
configMock.load.mockResolvedValue([{ key: SystemConfigKey.FFMPEG_ACCEL, value: TranscodeHWAccel.VAAPI }]);
assetMock.getByIds.mockResolvedValue([assetStub.video]);
await sut.handleVideoConversion({ id: assetStub.video.id }); await sut.handleVideoConversion({ id: assetStub.video.id });
expect(mediaMock.transcode).toHaveBeenCalledWith( expect(mediaMock.transcode).toHaveBeenCalledWith(
'/original/path.ext', '/original/path.ext',
'upload/encoded-video/user-id/as/se/asset-id.mp4', 'upload/encoded-video/user-id/as/se/asset-id.mp4',
{ {
inputOptions: ['-init_hw_device vaapi=accel:/dev/dri/renderD129', '-filter_hw_device accel'], inputOptions: ['-init_hw_device vaapi=accel:/dev/dri/renderD130', '-filter_hw_device accel'],
outputOptions: [ outputOptions: [
`-c:v h264_vaapi`, `-c:v h264_vaapi`,
'-c:a copy', '-c:a copy',

View File

@ -50,7 +50,8 @@ import { usePagination } from 'src/utils/pagination';
export class MediaService { export class MediaService {
private configCore: SystemConfigCore; private configCore: SystemConfigCore;
private storageCore: StorageCore; private storageCore: StorageCore;
private hasOpenCL?: boolean = undefined; private openCL: boolean | null = null;
private devices: string[] | null = null;
constructor( constructor(
@Inject(IAssetRepository) private assetRepository: IAssetRepository, @Inject(IAssetRepository) private assetRepository: IAssetRepository,
@ -492,36 +493,21 @@ export class MediaService {
private async getHWCodecConfig(config: SystemConfigFFmpegDto) { private async getHWCodecConfig(config: SystemConfigFFmpegDto) {
let handler: VideoCodecHWConfig; let handler: VideoCodecHWConfig;
let devices: string[];
switch (config.accel) { switch (config.accel) {
case TranscodeHWAccel.NVENC: { case TranscodeHWAccel.NVENC: {
handler = new NVENCConfig(config); handler = new NVENCConfig(config);
break; break;
} }
case TranscodeHWAccel.QSV: { case TranscodeHWAccel.QSV: {
devices = await this.storageRepository.readdir('/dev/dri'); handler = new QSVConfig(config, await this.getDevices());
handler = new QSVConfig(config, devices);
break; break;
} }
case TranscodeHWAccel.VAAPI: { case TranscodeHWAccel.VAAPI: {
devices = await this.storageRepository.readdir('/dev/dri'); handler = new VAAPIConfig(config, await this.getDevices());
handler = new VAAPIConfig(config, devices);
break; break;
} }
case TranscodeHWAccel.RKMPP: { case TranscodeHWAccel.RKMPP: {
if (this.hasOpenCL === undefined) { handler = new RKMPPConfig(config, await this.getDevices(), await this.hasOpenCL());
try {
const maliIcdStat = await this.storageRepository.stat('/etc/OpenCL/vendors/mali.icd');
const maliDeviceStat = await this.storageRepository.stat('/dev/mali0');
this.hasOpenCL = maliIcdStat.isFile() && maliDeviceStat.isCharacterDevice();
} catch {
this.logger.warn('OpenCL not available for transcoding, using CPU instead.');
this.hasOpenCL = false;
}
}
devices = await this.storageRepository.readdir('/dev/dri');
handler = new RKMPPConfig(config, devices, this.hasOpenCL);
break; break;
} }
default: { default: {
@ -572,4 +558,27 @@ export class MediaService {
return extractedSize >= targetSize; return extractedSize >= targetSize;
} }
private async getDevices() {
if (!this.devices) {
this.devices = await this.storageRepository.readdir('/dev/dri');
}
return this.devices;
}
private async hasOpenCL() {
if (this.openCL === null) {
try {
const maliIcdStat = await this.storageRepository.stat('/etc/OpenCL/vendors/mali.icd');
const maliDeviceStat = await this.storageRepository.stat('/dev/mali0');
this.openCL = maliIcdStat.isFile() && maliDeviceStat.isCharacterDevice();
} catch {
this.logger.warn('OpenCL not available for transcoding, using CPU instead.');
this.openCL = false;
}
}
return this.openCL;
}
} }