From c5c59ed040763a6e44da1f3ef5a59a19228199fa Mon Sep 17 00:00:00 2001 From: Mert <101130780+mertalev@users.noreply.github.com> Date: Wed, 6 May 2026 09:32:03 -0400 Subject: [PATCH] refactor(server): move video interface fetch to storage core (#28248) --- server/src/cores/storage.core.ts | 28 ++++++++++++++++++++++++++++ server/src/services/media.service.ts | 28 +++------------------------- 2 files changed, 31 insertions(+), 25 deletions(-) diff --git a/server/src/cores/storage.core.ts b/server/src/cores/storage.core.ts index 3345f6e129..d40518762d 100644 --- a/server/src/cores/storage.core.ts +++ b/server/src/cores/storage.core.ts @@ -18,6 +18,7 @@ import { MoveRepository } from 'src/repositories/move.repository'; import { PersonRepository } from 'src/repositories/person.repository'; import { StorageRepository } from 'src/repositories/storage.repository'; import { SystemMetadataRepository } from 'src/repositories/system-metadata.repository'; +import { VideoInterfaces } from 'src/types'; import { getAssetFile } from 'src/utils/asset.util'; import { getConfig } from 'src/utils/config'; @@ -299,6 +300,11 @@ export class StorageCore { return this.storageRepository.removeEmptyDirs(StorageCore.getBaseFolder(folder)); } + async getVideoInterfaces(): Promise { + const [dri, mali] = await Promise.all([this.getDevices(), this.hasMaliOpenCL()]); + return { dri, mali }; + } + private savePath(pathType: PathType, id: string, newPath: string) { switch (pathType) { case AssetPathType.Original: { @@ -330,4 +336,26 @@ export class StorageCore { static getTempPathInDir(dir: string): string { return join(dir, `${randomUUID()}.tmp`); } + + private async getDevices() { + try { + return await this.storageRepository.readdir('/dev/dri'); + } catch { + this.logger.debug('No devices found in /dev/dri.'); + return []; + } + } + + private async hasMaliOpenCL() { + try { + const [maliIcdStat, maliDeviceStat] = await Promise.all([ + this.storageRepository.stat('/etc/OpenCL/vendors/mali.icd'), + this.storageRepository.stat('/dev/mali0'), + ]); + return maliIcdStat.isFile() && maliDeviceStat.isCharacterDevice(); + } catch { + this.logger.debug('OpenCL not available for transcoding, so RKMPP acceleration will use CPU tonemapping'); + return false; + } + } } diff --git a/server/src/services/media.service.ts b/server/src/services/media.service.ts index 0b8a1f6702..a73eb3e22e 100644 --- a/server/src/services/media.service.ts +++ b/server/src/services/media.service.ts @@ -13,6 +13,7 @@ import { AudioCodec, Colorspace, ImageFormat, + ImmichWorker, JobName, JobStatus, QueueName, @@ -60,10 +61,9 @@ type ThumbnailAsset = NonNullable= targetSize; } - private async getDevices() { - try { - return await this.storageRepository.readdir('/dev/dri'); - } catch { - this.logger.debug('No devices found in /dev/dri.'); - return []; - } - } - - private async hasMaliOpenCL() { - try { - const [maliIcdStat, maliDeviceStat] = await Promise.all([ - this.storageRepository.stat('/etc/OpenCL/vendors/mali.icd'), - this.storageRepository.stat('/dev/mali0'), - ]); - return maliIcdStat.isFile() && maliDeviceStat.isCharacterDevice(); - } catch { - this.logger.debug('OpenCL not available for transcoding, so RKMPP acceleration will use CPU tonemapping'); - return false; - } - } - private async syncFiles( oldFiles: (AssetFile & { isProgressive: boolean; isTransparent: boolean })[], newFiles: UpsertFileOptions[],