Skip to content

Commit

Permalink
Ignore empty video frames (#52)
Browse files Browse the repository at this point in the history
  • Loading branch information
lukasIO authored Dec 9, 2024
1 parent 365606b commit b0295a0
Show file tree
Hide file tree
Showing 5 changed files with 27 additions and 11 deletions.
5 changes: 5 additions & 0 deletions .changeset/brave-ties-search.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@livekit/track-processors": patch
---

Ignore empty video frames
18 changes: 11 additions & 7 deletions src/ProcessorWrapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ export default class ProcessorWrapper<TransformerOptions extends Record<string,
constructor(transformer: TrackTransformer<TransformerOptions>, name: string) {
this.name = name;
this.transformer = transformer;
this.transformer.restart;
}

private async setup(opts: ProcessorOptions<Track.Kind>) {
Expand All @@ -46,15 +45,19 @@ export default class ProcessorWrapper<TransformerOptions extends Record<string,
// in order to prevent this, we force the resize mode to "none"
resizeMode: 'none',
});

this.sourceSettings = this.source.getSettings();
this.sourceDummy = opts.element;

if (!(this.sourceDummy instanceof HTMLVideoElement)) {
throw TypeError('Currently only video transformers are supported');
}

if (this.sourceDummy instanceof HTMLVideoElement) {
this.sourceDummy.height = this.sourceSettings.height ?? 300;
this.sourceDummy.width = this.sourceSettings.width ?? 300;
}
if (!(this.sourceDummy instanceof HTMLVideoElement)) {
throw TypeError('Currently only video transformers are supported');
}

// TODO explore if we can do all the processing work in a webworker
this.processor = new MediaStreamTrackProcessor({ track: this.source });

Expand All @@ -75,15 +78,16 @@ export default class ProcessorWrapper<TransformerOptions extends Record<string,
throw new TypeError('Expected both canvas and processor to be defined after setup');
}

let readableStream = this.processor.readable;
const readableStream = this.processor.readable;

await this.transformer.init({
outputCanvas: this.canvas,
inputElement: this.sourceDummy as HTMLVideoElement,
});
readableStream = readableStream.pipeThrough(this.transformer!.transformer!);

readableStream
const pipedStream = readableStream.pipeThrough(this.transformer!.transformer!);

pipedStream
.pipeTo(this.trackGenerator.writable)
.catch((e) => console.error('error when trying to pipe', e))
.finally(() => this.destroy());
Expand Down
10 changes: 8 additions & 2 deletions src/transformers/BackgroundTransformer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,9 @@ export default class BackgroundProcessor extends VideoTransformer<BackgroundOpti

// Skip loading the image here if update already loaded the image below
if (this.options?.imagePath && !this.backgroundImage) {
await this.loadBackground(this.options.imagePath).catch((err) => console.error("Error while loading processor background image: ", err));
await this.loadBackground(this.options.imagePath).catch((err) =>
console.error('Error while loading processor background image: ', err),
);
}
}

Expand All @@ -83,6 +85,10 @@ export default class BackgroundProcessor extends VideoTransformer<BackgroundOpti

async transform(frame: VideoFrame, controller: TransformStreamDefaultController<VideoFrame>) {
try {
if (!(frame instanceof VideoFrame)) {
console.debug('empty frame detected, ignoring');
return;
}
if (this.isDisabled) {
controller.enqueue(frame);
return;
Expand All @@ -107,7 +113,7 @@ export default class BackgroundProcessor extends VideoTransformer<BackgroundOpti
});
controller.enqueue(newFrame);
} finally {
frame.close();
frame?.close();
}
}

Expand Down
1 change: 1 addition & 0 deletions src/transformers/VideoTransformer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export default abstract class VideoTransformer<Options extends Record<string, un
if (!(inputVideo instanceof HTMLVideoElement)) {
throw TypeError('Video transformer needs a HTMLVideoElement as input');
}

this.transformer = new TransformStream({
transform: (frame, controller) => this.transform(frame, controller),
});
Expand Down
4 changes: 2 additions & 2 deletions tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"compilerOptions": {
"lib": ["DOM", "ES2017"],
"target": "ES2017" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */,
"lib": ["DOM", "ES2018"],
"target": "ES2018" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */,
"module": "ES2020" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */,
"rootDir": "./",
"declarationDir": "./dist",
Expand Down

0 comments on commit b0295a0

Please sign in to comment.