ov-components: streamline virtual background processing

pull/856/head
Carlos Santos 2025-12-05 15:40:40 +01:00
parent 007297e4ff
commit 435db94254
1 changed files with 21 additions and 54 deletions

View File

@ -1,13 +1,13 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { BackgroundOptions, BackgroundProcessor, ProcessorWrapper } from '@livekit/track-processors';
import { LocalVideoTrack, Track } from 'livekit-client';
import { BehaviorSubject, Observable } from 'rxjs'; import { BehaviorSubject, Observable } from 'rxjs';
import { BackgroundEffect, EffectType } from '../../models/background-effect.model'; import { BackgroundEffect, EffectType } from '../../models/background-effect.model';
import { ParticipantService } from '../participant/participant.service';
import { OpenViduService } from '../openvidu/openvidu.service';
import { StorageService } from '../storage/storage.service';
import { LocalVideoTrack, Track } from 'livekit-client';
import { BackgroundBlur, BackgroundOptions, ProcessorWrapper, VirtualBackground } from '@livekit/track-processors';
import { LoggerService } from '../logger/logger.service';
import { ILogger } from '../../models/logger.model'; import { ILogger } from '../../models/logger.model';
import { LoggerService } from '../logger/logger.service';
import { OpenViduService } from '../openvidu/openvidu.service';
import { ParticipantService } from '../participant/participant.service';
import { StorageService } from '../storage/storage.service';
/** /**
* @internal * @internal
@ -47,6 +47,8 @@ export class VirtualBackgroundService {
private HARD_BLUR_INTENSITY = 60; private HARD_BLUR_INTENSITY = 60;
private log: ILogger; private log: ILogger;
private processor: ProcessorWrapper<BackgroundOptions>;
constructor( constructor(
private participantService: ParticipantService, private participantService: ParticipantService,
private openviduService: OpenViduService, private openviduService: OpenViduService,
@ -55,6 +57,7 @@ export class VirtualBackgroundService {
) { ) {
this.log = this.loggerSrv.get('VirtualBackgroundService'); this.log = this.loggerSrv.get('VirtualBackgroundService');
this.backgroundIdSelected$ = this.backgroundIdSelected.asObservable(); this.backgroundIdSelected$ = this.backgroundIdSelected.asObservable();
this.processor = BackgroundProcessor({ mode: 'disabled' });
} }
getBackgrounds(): BackgroundEffect[] { getBackgrounds(): BackgroundEffect[] {
@ -95,17 +98,11 @@ export class VirtualBackgroundService {
const currentProcessor = cameraTrack.getProcessor() as ProcessorWrapper<BackgroundOptions>; const currentProcessor = cameraTrack.getProcessor() as ProcessorWrapper<BackgroundOptions>;
// Check if the background is the same type as the previous one if (currentProcessor) {
if (this.hasSameTypeAsPreviousOne(bg.type) && currentProcessor) {
await this.replaceBackground(currentProcessor, bg); await this.replaceBackground(currentProcessor, bg);
} else { } else {
// If the background is different, remove the previous one and apply the new one await this.applyProcessorToCameraTrack(cameraTrack, this.processor);
const newProcessor = this.getBackgroundProcessor(bg); await this.replaceBackground(this.processor, bg);
if (!newProcessor) {
this.log.e('No processor found for the background effect.');
return;
}
await this.applyProcessorToCameraTrack(cameraTrack, newProcessor);
} }
this.storageService.setBackground(bg.id); this.storageService.setBackground(bg.id);
@ -117,49 +114,33 @@ export class VirtualBackgroundService {
private getBackgroundOptions(bg: BackgroundEffect): BackgroundOptions { private getBackgroundOptions(bg: BackgroundEffect): BackgroundOptions {
if (bg.type === EffectType.IMAGE && bg.src) { if (bg.type === EffectType.IMAGE && bg.src) {
return { imagePath: bg.src }; return { imagePath: bg.src, blurRadius: undefined, backgroundDisabled: false };
} else if (bg.type === EffectType.BLUR) { } else if (bg.type === EffectType.BLUR) {
return { return {
blurRadius: bg.id === 'soft_blur' ? this.SOFT_BLUR_INTENSITY : this.HARD_BLUR_INTENSITY blurRadius: bg.id === 'soft_blur' ? this.SOFT_BLUR_INTENSITY : this.HARD_BLUR_INTENSITY,
imagePath: undefined,
backgroundDisabled: false
}; };
} }
return {}; return { backgroundDisabled: true };
} }
async removeBackground() { async removeBackground() {
if (this.isBackgroundApplied()) { if (this.isBackgroundApplied()) {
this.backgroundIdSelected.next('no_effect'); this.backgroundIdSelected.next('no_effect');
const cameraTrack = this.getCameraTrack(); const cameraTrack = this.getCameraTrack();
if (cameraTrack) { const processor = cameraTrack?.getProcessor() as ProcessorWrapper<BackgroundOptions>;
if (processor) {
try { try {
await cameraTrack.stopProcessor(); await processor.updateTransformerOptions({ backgroundDisabled: true });
} catch (e) { } catch (e) {
this.log.w('Error stopping processor:', e); this.log.w('Error disabling processor:', e);
} }
} }
this.storageService.removeBackground(); this.storageService.removeBackground();
} }
} }
private getBackgroundProcessor(bg: BackgroundEffect): ProcessorWrapper<BackgroundOptions> | undefined {
switch (bg.type) {
case EffectType.IMAGE:
if (bg.src) {
return VirtualBackground(bg.src);
}
break;
case EffectType.BLUR:
if (bg.id === 'soft_blur') {
return BackgroundBlur(this.SOFT_BLUR_INTENSITY);
} else if (bg.id === 'hard_blur') {
return BackgroundBlur(this.HARD_BLUR_INTENSITY);
}
break;
}
return undefined;
}
/** /**
* Gets the camera track from either the published tracks (if in room) or local tracks (if in prejoin) * Gets the camera track from either the published tracks (if in room) or local tracks (if in prejoin)
* @returns The camera LocalTrack or undefined if not found * @returns The camera LocalTrack or undefined if not found
@ -215,18 +196,4 @@ export class VirtualBackgroundService {
throw error; throw error;
} }
} }
/**
* Checks if the currently selected background has the same effect type as the provided one.
*
* @param type - The effect type to compare with the currently selected background.
* @returns `true` if the currently selected background has the same effect type, `false` otherwise.
* @private
*/
private hasSameTypeAsPreviousOne(type: EffectType): boolean {
const currentBgId = this.backgroundIdSelected.getValue();
const currentBg = this.backgrounds.find((b) => b.id === currentBgId);
const isSameEffectType = currentBg && currentBg.type === type;
return !!isSameEffectType;
}
} }