-
Notifications
You must be signed in to change notification settings - Fork 18
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
Conversation
@@ -9,12 +10,30 @@ interface LocalStreamEvents { | |||
[LocalStreamEventNames.ConstraintsChange]: TypedEvent<() => void>; | |||
} | |||
|
|||
export type TrackEffect = BaseEffect; |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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?
src/media/local-stream.ts
Outdated
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); | ||
} | ||
}); |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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
Outdated
|
||
// 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); |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated.
c68a261
to
363f792
Compare
src/media/local-stream.ts
Outdated
await effect.dispose(); | ||
throw new Error(`Effect already exists with name "${name}"`); |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
src/media/local-stream.ts
Outdated
/** | ||
* A stream which originates on the local device. | ||
*/ | ||
abstract class _LocalStream extends Stream { | ||
[LocalStreamEventNames.ConstraintsChange] = new TypedEvent<() => void>(); | ||
|
||
private effects: EffectItem[] = []; | ||
|
||
private loadingEffects: string[] = []; |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated.
363f792
to
791e377
Compare
src/media/local-stream.spec.ts
Outdated
mockStream.getTracks()[0].enabled = true; | ||
|
||
localStream.setMuted(true); | ||
expect(privateAccess(localStream).outputStream.getTracks()[0].enabled).toBe(false); |
There was a problem hiding this comment.
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
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated.
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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);
src/media/local-stream.ts
Outdated
@@ -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) { |
There was a problem hiding this comment.
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
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated.
e4ab49b
to
97e41fb
Compare
There was a problem hiding this 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
src/media/local-stream.spec.ts
Outdated
const addEffectPromise = localStream.addEffect('test-effect', effect as unknown as BaseEffect); | ||
|
||
await expect(addEffectPromise).resolves.toBeUndefined(); | ||
expect(privateAccess(localStream).outputStream.getTracks()[0]).toBe(effectTrack); |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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)
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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
There was a problem hiding this 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
60b80b3
to
138529b
Compare
* 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]>
* 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
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.