refactor(server): move video interface fetch to storage core (#28248)

This commit is contained in:
Mert
2026-05-06 09:32:03 -04:00
committed by GitHub
parent 576b1eb999
commit c5c59ed040
2 changed files with 31 additions and 25 deletions
+28
View File
@@ -18,6 +18,7 @@ import { MoveRepository } from 'src/repositories/move.repository';
import { PersonRepository } from 'src/repositories/person.repository'; import { PersonRepository } from 'src/repositories/person.repository';
import { StorageRepository } from 'src/repositories/storage.repository'; import { StorageRepository } from 'src/repositories/storage.repository';
import { SystemMetadataRepository } from 'src/repositories/system-metadata.repository'; import { SystemMetadataRepository } from 'src/repositories/system-metadata.repository';
import { VideoInterfaces } from 'src/types';
import { getAssetFile } from 'src/utils/asset.util'; import { getAssetFile } from 'src/utils/asset.util';
import { getConfig } from 'src/utils/config'; import { getConfig } from 'src/utils/config';
@@ -299,6 +300,11 @@ export class StorageCore {
return this.storageRepository.removeEmptyDirs(StorageCore.getBaseFolder(folder)); return this.storageRepository.removeEmptyDirs(StorageCore.getBaseFolder(folder));
} }
async getVideoInterfaces(): Promise<VideoInterfaces> {
const [dri, mali] = await Promise.all([this.getDevices(), this.hasMaliOpenCL()]);
return { dri, mali };
}
private savePath(pathType: PathType, id: string, newPath: string) { private savePath(pathType: PathType, id: string, newPath: string) {
switch (pathType) { switch (pathType) {
case AssetPathType.Original: { case AssetPathType.Original: {
@@ -330,4 +336,26 @@ export class StorageCore {
static getTempPathInDir(dir: string): string { static getTempPathInDir(dir: string): string {
return join(dir, `${randomUUID()}.tmp`); 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;
}
}
} }
+3 -25
View File
@@ -13,6 +13,7 @@ import {
AudioCodec, AudioCodec,
Colorspace, Colorspace,
ImageFormat, ImageFormat,
ImmichWorker,
JobName, JobName,
JobStatus, JobStatus,
QueueName, QueueName,
@@ -60,10 +61,9 @@ type ThumbnailAsset = NonNullable<Awaited<ReturnType<AssetJobRepository['getForG
export class MediaService extends BaseService { export class MediaService extends BaseService {
videoInterfaces: VideoInterfaces = { dri: [], mali: false }; videoInterfaces: VideoInterfaces = { dri: [], mali: false };
@OnEvent({ name: 'AppBootstrap' }) @OnEvent({ name: 'AppBootstrap', workers: [ImmichWorker.Microservices] })
async onBootstrap() { async onBootstrap() {
const [dri, mali] = await Promise.all([this.getDevices(), this.hasMaliOpenCL()]); this.videoInterfaces = await this.storageCore.getVideoInterfaces();
this.videoInterfaces = { dri, mali };
} }
@OnJob({ name: JobName.AssetGenerateThumbnailsQueueAll, queue: QueueName.ThumbnailGeneration }) @OnJob({ name: JobName.AssetGenerateThumbnailsQueueAll, queue: QueueName.ThumbnailGeneration })
@@ -789,28 +789,6 @@ export class MediaService extends BaseService {
return extractedSize >= targetSize; return extractedSize >= 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( private async syncFiles(
oldFiles: (AssetFile & { isProgressive: boolean; isTransparent: boolean })[], oldFiles: (AssetFile & { isProgressive: boolean; isTransparent: boolean })[],
newFiles: UpsertFileOptions[], newFiles: UpsertFileOptions[],