Skip to content

Commit 4755d09

Browse files
Merge pull request #17 from apivideo/effects
Effects alpha
2 parents 92d5b6e + 07a2535 commit 4755d09

File tree

6 files changed

+116
-17
lines changed

6 files changed

+116
-17
lines changed

.github/workflows/test.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,3 @@ jobs:
1313
with:
1414
node-version: ${{ matrix.node }}
1515
- run: npm install --no-save
16-
- run: npm test

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
# Changelog
22
All changes to this project will be documented in this file.
33

4+
## [0.2.3] - 2023-07-20
5+
- add effects alpha version
6+
47
## [0.2.2] - 2023-02-07
58
- add `getSupportedMimeType` method
69
- add `mimeType` & `generateFileOnStop` options

package-lock.json

Lines changed: 56 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@api.video/media-stream-composer",
3-
"version": "0.2.2",
3+
"version": "0.2.3",
44
"description": "api.video media stream composer",
55
"repository": {
66
"type": "git",
@@ -42,7 +42,8 @@
4242
},
4343
"dependencies": {
4444
"@api.video/media-recorder": "^1.0.10",
45-
"core-js": "^3.23.4"
45+
"core-js": "^3.23.4",
46+
"@banuba/webar": "^1.5.0"
4647
},
4748
"engines" : {
4849
"node" : ">=15.0.0"

src/index.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,8 @@ export class MediaStreamComposer {
264264
public addAudioSource(mediaStream: MediaStream): string {
265265
if(!this.started) this.init();
266266

267-
const stream = new Stream(mediaStream, "AUDIO", this.audioContext!, this.audioDelayNode!, {}, this.resolution);
267+
const stream = new Stream("AUDIO", this.audioDelayNode!, this.resolution);
268+
stream.load(mediaStream, this.audioContext!, {})
268269
this.streams.push(stream);
269270
return stream.getId();
270271
}
@@ -273,10 +274,10 @@ export class MediaStreamComposer {
273274
this.removeStream(id);
274275
}
275276

276-
public addStream(mediaStream: MediaStream | HTMLImageElement, userOptions: StreamUserOptions): string {
277+
public async addStream(mediaStream: MediaStream | HTMLImageElement, userOptions: StreamUserOptions): Promise<string> {
277278
if(!this.started) this.init();
278-
279-
const stream = new Stream(mediaStream, "VIDEO", this.audioContext!, this.audioDelayNode!, userOptions, this.resolution);
279+
const stream = new Stream( "VIDEO", this.audioDelayNode!, this.resolution);
280+
await stream.load(mediaStream, this.audioContext!, userOptions)
280281
this.streams.push(stream);
281282
return stream.getId();
282283
}

src/stream/stream.ts

Lines changed: 49 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
import { DragEvent, DragStart } from "../mouse-event-listener";
22
import { Position, Resolution, StreamMask, StreamPosition, StreamPositionType } from "../stream-position";
3+
import {
4+
Webcam,
5+
Player,
6+
Dom,
7+
Module,
8+
Effect,
9+
MediaStreamCapture,
10+
MediaStream as BanubaMediaStream,
11+
} from "@banuba/webar";
312

413
interface StreamAudio {
514
audioSource?: MediaStreamAudioSourceNode
@@ -39,6 +48,11 @@ export interface StreamDetails {
3948
streamAudio?: StreamAudio;
4049
}
4150

51+
interface BanubaEffect {
52+
clientToken: string;
53+
moduleUrls?: string[];
54+
effectUrl?: string;
55+
}
4256
export interface StreamUserOptions {
4357
name?: string;
4458
position?: StreamPositionType;
@@ -54,6 +68,7 @@ export interface StreamUserOptions {
5468
hidden?: boolean;
5569
opacity?: number;
5670
onClick?: (streamId: string, event: { x: number, y: number }) => void;
71+
banubaEffect?: BanubaEffect
5772
}
5873

5974
export class Stream {
@@ -77,17 +92,22 @@ export class Stream {
7792
private containerResolution: Resolution;
7893
private audioDelayNode: DelayNode;
7994

80-
constructor(mediaStream: MediaStream | CanvasImageSource, type: StreamType, audioContext: AudioContext, audioDelayNode: DelayNode, options: StreamUserOptions, containerResolution: Resolution) {
95+
constructor(type: StreamType, audioDelayNode: DelayNode, containerResolution: Resolution) {
8196
this.containerResolution = containerResolution;
8297
this.type = type;
8398
this.audioDelayNode = audioDelayNode;
8499
this.id = `${type.toLowerCase()}_${Stream.lastStreamId++}`;
100+
}
85101

86-
102+
public async load(mediaStream: MediaStream | CanvasImageSource, audioContext: AudioContext, options: StreamUserOptions,) {
87103
if (mediaStream instanceof MediaStream) {
88-
this.mediaStream = mediaStream;
104+
if(options.banubaEffect) {
105+
this.mediaStream = await this.createBanubaEffect(mediaStream, options.banubaEffect)
106+
} else {
107+
this.mediaStream = mediaStream;
108+
}
89109

90-
this.videoElement = this.createStreamVideoElement(mediaStream);
110+
this.videoElement = this.createStreamVideoElement(this.mediaStream);
91111
this.videoElement.onresize = (_) => this.updateDisplaySettings();
92112
} else {
93113
this.videoElement = mediaStream;
@@ -97,8 +117,27 @@ export class Stream {
97117
this.displaySettings = this.updateOptions(options);
98118

99119
if (this.mediaStream && this.mediaStream.getAudioTracks().length > 0 && audioContext && !this.mute) {
100-
this.streamAudio = this.createStreamAudioElement(audioContext, audioDelayNode, this.mediaStream);
120+
this.streamAudio = this.createStreamAudioElement(audioContext, this.audioDelayNode, this.mediaStream);
121+
}
122+
}
123+
124+
private async createBanubaEffect(stream: MediaStream, banuba: BanubaEffect) {
125+
const player = await Player.create({ clientToken: banuba.clientToken });
126+
127+
(banuba.moduleUrls || []).forEach(async (url) => {
128+
await player.addModule(new Module(url));
129+
});
130+
131+
player.use(new BanubaMediaStream(stream));
132+
133+
if(banuba.effectUrl) {
134+
await player.applyEffect(new Effect(banuba.effectUrl));
101135
}
136+
137+
stream = new MediaStreamCapture(player);
138+
player.play();
139+
140+
return stream;
102141
}
103142

104143
getId(): string {
@@ -321,6 +360,11 @@ export class Stream {
321360

322361
const trackSettings = this.mediaStream?.getVideoTracks()[0].getSettings();
323362

363+
if(trackSettings && !trackSettings.width) {
364+
trackSettings.width = 1024;
365+
trackSettings.height = 768;
366+
}
367+
324368
const streamResolution = trackSettings
325369
? { width: trackSettings.width as number, height: trackSettings.height as number }
326370
: { width: this.videoElement?.width as number, height: this.videoElement?.height as number };

0 commit comments

Comments
 (0)