diff --git a/src/domain/session/room/CallViewModel.ts b/src/domain/session/room/CallViewModel.ts index 020c9f17..9c0eae9a 100644 --- a/src/domain/session/room/CallViewModel.ts +++ b/src/domain/session/room/CallViewModel.ts @@ -136,7 +136,7 @@ class OwnMemberViewModel extends ViewModel implements IStreamViewModel } get stream(): Stream | undefined { - return this.call.localMedia?.userMedia; + return this.call.localMedia?.userMediaPreview; } private get call(): GroupCall { diff --git a/src/matrix/calls/LocalMedia.ts b/src/matrix/calls/LocalMedia.ts index f02cd11b..25d6862f 100644 --- a/src/matrix/calls/LocalMedia.ts +++ b/src/matrix/calls/LocalMedia.ts @@ -20,11 +20,24 @@ import {SDPStreamMetadata} from "./callEventTypes"; import {getStreamVideoTrack, getStreamAudioTrack} from "./common"; export class LocalMedia { + // the userMedia stream without audio, to play in the UI + // without our own audio being played back to us + public readonly userMediaPreview?: Stream; + constructor( public readonly userMedia?: Stream, public readonly screenShare?: Stream, public readonly dataChannelOptions?: RTCDataChannelInit, - ) {} + ) { + if (userMedia && userMedia.getVideoTracks().length > 0) { + this.userMediaPreview = userMedia.clone(); + const audioTrack = getStreamAudioTrack(this.userMediaPreview); + if (audioTrack) { + audioTrack.stop(); + this.userMediaPreview.removeTrack(audioTrack); + } + } + } withUserMedia(stream: Stream) { return new LocalMedia(stream, this.screenShare, this.dataChannelOptions); @@ -63,6 +76,7 @@ export class LocalMedia { dispose() { getStreamAudioTrack(this.userMedia)?.stop(); getStreamVideoTrack(this.userMedia)?.stop(); + getStreamVideoTrack(this.userMediaPreview)?.stop(); getStreamVideoTrack(this.screenShare)?.stop(); } } diff --git a/src/matrix/calls/group/GroupCall.ts b/src/matrix/calls/group/GroupCall.ts index 0931d4ea..d65ea838 100644 --- a/src/matrix/calls/group/GroupCall.ts +++ b/src/matrix/calls/group/GroupCall.ts @@ -216,8 +216,8 @@ export class GroupCall extends EventEmitter<{change: never}> { // you might be muted because you don't have a track or because // you actively chosen to mute // (which we want to respect in the future when you add a track) + muteSettings.updateTrackInfo(joinedData.localMedia.userMedia); joinedData.localMuteSettings = muteSettings; - joinedData.localMuteSettings.updateTrackInfo(joinedData.localMedia.userMedia); if (!prevMuteSettings.equals(muteSettings)) { await Promise.all(Array.from(this._members.values()).map(m => { return m.setMuted(joinedData.localMuteSettings);