Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: effects api #52

Merged
merged 4 commits into from
May 25, 2023
Merged

feat: effects api #52

merged 4 commits into from
May 25, 2023

Conversation

mccarthytyler
Copy link
Contributor

Start of the effects API. Right now it requires BaseEffect from @webex/web-media-effects which brings in quite a few dependencies that we probably don't want.

@@ -9,12 +10,30 @@ interface LocalStreamEvents {
[LocalStreamEventNames.ConstraintsChange]: TypedEvent<() => void>;
}

export type TrackEffect = BaseEffect;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can just use the name web-media-effects defines (BaseEffect). If anything, maybe web-media-effects should rename BaseEffect to TrackEffect?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did web-media-effects end up defining a TrackEffect interface? Or it still just has BaseEffect?

Comment on lines 90 to 102
const outputTrack = await effect.load(this.outputStream.getTracks()[0]);
this.effects.push({ name, effect });
replaceTrack(this.outputStream, outputTrack);

// When the effect's track is updated, update the next effect or output stream.
effect.on(EffectEvent.TrackUpdated, (track: MediaStreamTrack) => {
const effectIndex = this.effects.findIndex((i) => i.name === name);
if (effectIndex === this.effects.length - 1) {
replaceTrack(this.outputStream, track);
} else {
this.effects[effectIndex + 1]?.effect.replaceInputTrack(track);
}
});
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to do the 'pendingEffect' scheme that was recently added in webrtc-core main?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added.

src/media/local-stream.ts Show resolved Hide resolved

// When the effect's track is updated, update the next effect or output stream.
effect.on(EffectEvent.TrackUpdated, (track: MediaStreamTrack) => {
const effectIndex = this.effects.findIndex((i) => i.name === name);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: use e instead of i here? i makes me think it's an index.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated.

Comment on lines 100 to 101
await effect.dispose();
throw new Error(`Effect already exists with name "${name}"`);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to the web client team, there's a use case to replace an earlier version of an effect with a newer one (which may have different params)--I think that's what the current webrtc-core supports. If we want to enforce they dispose the old one first, we should check in with them.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah I must have misread. For now I can replicate their implementation.

/**
* A stream which originates on the local device.
*/
abstract class _LocalStream extends Stream {
[LocalStreamEventNames.ConstraintsChange] = new TypedEvent<() => void>();

private effects: EffectItem[] = [];

private loadingEffects: string[] = [];
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because order isn't important here, I think this could be a map keyed by the effect name, which would make the lookups a bit easier.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated.

mockStream.getTracks()[0].enabled = true;

localStream.setMuted(true);
expect(privateAccess(localStream).outputStream.getTracks()[0].enabled).toBe(false);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can't we verify these on mockStream instead of using privateAccess?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think this change may have gotten lost?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed the above code to:

mockStream.getTracks()[0].enabled = true;

localStream.setMuted(true);
expect(mockStream.getTracks()[0].enabled).toBe(false);
localStream.setMuted(false);
expect(mockStream.getTracks()[0].enabled).toBe(true);

@@ -130,7 +130,7 @@ abstract class _LocalStream extends Stream {
*/
async disposeEffects(): Promise<void> {
// Dispose of any effects currently in use
if (this.effects.length > 0) {
if (this.loadingEffects.size > 0) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we do want this to be this.effects?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated.

Copy link
Collaborator

@bbaldino bbaldino left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

one more nit on the tests, but otherwise lgtm

const addEffectPromise = localStream.addEffect('test-effect', effect as unknown as BaseEffect);

await expect(addEffectPromise).resolves.toBeUndefined();
expect(privateAccess(localStream).outputStream.getTracks()[0]).toBe(effectTrack);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think these uses of privateAccess can be changed too?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In these cases I think we want to make sure the output stream has the track that the effect is outputting

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok...how about just having TestLocalStream expose it?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Though, to be honest, I can't remember why Stream doesn't expose a getter for outputStream, I'm pretty sure we'll end up with one (even it's just an abstract getter at the Stream level)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I ended up having TestLocalStream expose it, I can go back and update if/when the getter is added. Is that something we want to add on this PR?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok cool. Nah we'll do that later

Copy link
Collaborator

@bbaldino bbaldino left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

one more nit on the tests, but otherwise lgtm

@mccarthytyler mccarthytyler merged commit 3c96f27 into stream_classes May 25, 2023
@mccarthytyler mccarthytyler deleted the tymccart/effect-api branch May 25, 2023 15:51
brycetham added a commit that referenced this pull request Jul 19, 2023
* feat: new stream classes initial commit (#49)

* feat: new stream classes initial commit

* refactor: originStream -> inputStream

* feat: integrate new stream types (#50)

* feat: replace LocalMicrophoneTrack with LocalMicrophoneStream

* refactor: replace LocalDisplayTrack with LocalDisplayStream

* refactor: replace LocalCameraTrack with LocalCameraStream

* refactor: remove LocalTrack

* refactor: rename originTrack -> inputTrack

* feat: effects api (#52)

* feat: add effects api

* fix: add loadingeffects protection

* test: localstream unit tests

* chore: upgrade effects version

* refactor: add methods and update events for stream classes (#55)

* refactor: add support for wcme refactor

* chore: minor updates to LocalStream and unit tests

---------

Co-authored-by: Bryce Tham <[email protected]>

* feat: limit appliable constraints (#56)

* feat: limit appliable constraints

* refactor: pick VideoDeviceConstraints from MediaTrackConstraints

---------

Co-authored-by: Bryce Tham <[email protected]>

* feat: listen to track events and additional updates to stream classes (#57)

* feat: listen to track events and additional updates to stream classes

* fix: preserve outputStream in changeOutputTrack

* chore: change outputStream to readonly

* chore: update unit tests and comments

---------

Co-authored-by: Bryce Tham <[email protected]>

* chore: update docs and errors in device management API

* fix: stop outputTrack on LocalStream stop

---------

Co-authored-by: bbaldino <[email protected]>
Co-authored-by: Tyler McCarthy <[email protected]>
Co-authored-by: Bryce Tham <[email protected]>
bbaldino pushed a commit that referenced this pull request Jul 19, 2023
# [1.8.0](v1.7.1...v1.8.0) (2023-07-19)

### Features

* convert track-based classes into stream-based classes ([#58](#58)) ([a543678](a543678)), closes [#49](#49) [#50](#50) [#52](#52) [#55](#55)
brycetham added a commit that referenced this pull request Jul 19, 2023
* feat: new stream classes initial commit (#49)

* feat: new stream classes initial commit

* refactor: originStream -> inputStream

* feat: integrate new stream types (#50)

* feat: replace LocalMicrophoneTrack with LocalMicrophoneStream

* refactor: replace LocalDisplayTrack with LocalDisplayStream

* refactor: replace LocalCameraTrack with LocalCameraStream

* refactor: remove LocalTrack

* refactor: rename originTrack -> inputTrack

* feat: effects api (#52)

* feat: add effects api

* fix: add loadingeffects protection

* test: localstream unit tests

* chore: upgrade effects version

* refactor: add methods and update events for stream classes (#55)

* refactor: add support for wcme refactor

* chore: minor updates to LocalStream and unit tests

---------

Co-authored-by: Bryce Tham <[email protected]>

* feat: limit appliable constraints (#56)

* feat: limit appliable constraints

* refactor: pick VideoDeviceConstraints from MediaTrackConstraints

---------

Co-authored-by: Bryce Tham <[email protected]>

* feat: listen to track events and additional updates to stream classes (#57)

* feat: listen to track events and additional updates to stream classes

* fix: preserve outputStream in changeOutputTrack

* chore: change outputStream to readonly

* chore: update unit tests and comments

---------

Co-authored-by: Bryce Tham <[email protected]>

* chore: update docs and errors in device management API

* fix: stop outputTrack on LocalStream stop

---------

Co-authored-by: bbaldino <[email protected]>
Co-authored-by: Tyler McCarthy <[email protected]>
Co-authored-by: Bryce Tham <[email protected]>

BREAKING CHANGE: convert track-based classes into stream-based classes
bbaldino pushed a commit that referenced this pull request Jul 19, 2023
# [1.8.0](v1.7.1...v1.8.0) (2023-07-19)

### Features

* convert track-based classes into stream-based classes ([#59](#59)) ([77e525c](77e525c)), closes [#49](#49) [#50](#50) [#52](#52) [#55](#55)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants