mirror of
https://github.com/vector-im/element-call.git
synced 2026-10-16 23:45:50 +00:00
Attach background effects through one switchable pipeline
- One pipeline, shared by the pre-join preview and the call, attached the first time an effect is wanted and never detached after; turning blur off switches it to a disabled mode in place. Main dropped the processor whenever blur went off, and a pipeline taken off the camera is destroyed and re-primed, so each time blur came back one unprocessed frame went out. Built once, the priming frame is spent once. - Still driven by the existing blur setting: nothing a user sees changes. - Its logic is BackgroundEffects in src/state/, which the provider only builds, so the tests drive it without rendering anything. - Disabled drops the blur radius too. The SDK's disabled mode keeps it, and with a radius every frame is still segmented and thrown away; with neither a radius nor a picture, frames pass untouched. - Switches run one at a time and skip any overtaken, so an earlier, slower switch can't land after a later choice. - Builds, rebuilds and teardowns of the pipeline run one at a time (OneStepPipeline). The preview's and the call's tracks attach and stop it independently, and the SDK's wrapper holds one track's streams: two builds at once overwrite each other's, and a stop during a build does nothing. - Every camera track starts with the pipeline on: the room's capture defaults follow it, and a camera turned off before the first effect is replaced on turning it on, since a stopped track can't take one. One attached after publishing lets the room through while it is built. - BlurBackgroundTransformer becomes BackgroundEffectTransformer: it also sits disabled, and its init applies that state as the SDK's would. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
Copyright 2026 Element Creations Ltd.
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
Please see LICENSE in the repository root for full details.
|
||||
*/
|
||||
|
||||
import { BackgroundProcessorWrapper } from "@livekit/track-processors";
|
||||
|
||||
type InitOptions = Parameters<BackgroundProcessorWrapper["init"]>[0];
|
||||
type DestroyOptions = Parameters<BackgroundProcessorWrapper["destroy"]>[0];
|
||||
|
||||
/**
|
||||
* A background pipeline that is built, rebuilt and destroyed one step at a
|
||||
* time. The camera tracks sharing it attach and stop it independently, and
|
||||
* the SDK's wrapper holds a single track's streams: two builds at once
|
||||
* overwrite each other's, and a destroy during a build does nothing.
|
||||
*/
|
||||
export class OneStepPipeline extends BackgroundProcessorWrapper {
|
||||
private steps: Promise<void> = Promise.resolve();
|
||||
|
||||
public override async init(opts: InitOptions): Promise<void> {
|
||||
return this.inTurn(async () => super.init(opts));
|
||||
}
|
||||
|
||||
// The SDK's restart calls init and destroy, which would wait on itself.
|
||||
public override async restart(opts: InitOptions): Promise<void> {
|
||||
return this.inTurn(async () => {
|
||||
await super.destroy({ willProcessorRestart: true });
|
||||
await super.init(opts);
|
||||
});
|
||||
}
|
||||
|
||||
public override async destroy(options?: DestroyOptions): Promise<void> {
|
||||
return this.inTurn(async () => super.destroy(options));
|
||||
}
|
||||
|
||||
private async inTurn(step: () => Promise<void>): Promise<void> {
|
||||
const turn = this.steps.then(step);
|
||||
this.steps = turn.catch(() => {});
|
||||
return turn;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user