-
Notifications
You must be signed in to change notification settings - Fork 13.8k
fix: allow screen sharing without media devices #41682
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
Changes from all commits
d380e5a
0a28e48
44c72fb
062416d
f951a6e
993dfab
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -155,9 +155,6 @@ export class MediaCallWebRTCProcessor implements IWebRTCProcessor { | |
| if (this.stopped) { | ||
| throw new Error('WebRTC Processor has already been stopped.'); | ||
| } | ||
| if (!this.inputTrack) { | ||
| throw new Error('no-input-track'); | ||
| } | ||
|
|
||
| await this.initialization; | ||
|
|
||
|
|
@@ -339,8 +336,11 @@ export class MediaCallWebRTCProcessor implements IWebRTCProcessor { | |
| private updateAudioDirectionBeforeNegotiation(): void { | ||
| // Before the negotiation, we set the direction based on our own state only | ||
| // We'll tell the SDK that we want to send audio and, depending on the "on hold" state, also receive it | ||
| const desiredDirection = this.held ? 'sendonly' : 'sendrecv'; | ||
| const desiredDirection = this.getDesiredAudioDirection(); | ||
|
|
||
| if (!this.getTransceivers('audio').length) { | ||
| this.peer.addTransceiver('audio', { direction: desiredDirection }); | ||
| } | ||
| this.updateDirectionBeforeNegotiation('audio', desiredDirection); | ||
| } | ||
|
|
||
|
|
@@ -351,8 +351,8 @@ export class MediaCallWebRTCProcessor implements IWebRTCProcessor { | |
|
|
||
| // If we didn't do this, everything would still work, but the browser would trigger redundant renegotiations whenever the directions mismatch | ||
|
|
||
| const desiredDirection = this.held ? 'sendonly' : 'sendrecv'; | ||
| const acceptableDirection = this.held ? 'inactive' : 'recvonly'; | ||
| const desiredDirection = this.getDesiredAudioDirection(); | ||
| const acceptableDirection = this.held || !this.inputTrack ? 'inactive' : 'recvonly'; | ||
|
|
||
| this.updateDirectionAfterNegotiation('audio', desiredDirection, acceptableDirection); | ||
| } | ||
|
|
@@ -470,8 +470,8 @@ export class MediaCallWebRTCProcessor implements IWebRTCProcessor { | |
| return; | ||
| } | ||
|
|
||
| const desiredDirection = this.held ? 'sendonly' : 'sendrecv'; | ||
| const acceptableDirection = this.held ? 'inactive' : 'recvonly'; | ||
| const desiredDirection = this.getDesiredAudioDirection(); | ||
| const acceptableDirection = this.held || !this.inputTrack ? 'inactive' : 'recvonly'; | ||
|
|
||
| const transceivers = this.getTransceivers('audio'); | ||
| for (const transceiver of transceivers) { | ||
|
|
@@ -486,6 +486,14 @@ export class MediaCallWebRTCProcessor implements IWebRTCProcessor { | |
| } | ||
| } | ||
|
|
||
| private getDesiredAudioDirection(): RTCRtpTransceiverDirection { | ||
| if (!this.inputTrack) { | ||
| return this.held ? 'inactive' : 'recvonly'; | ||
| } | ||
|
|
||
| return this.held ? 'sendonly' : 'sendrecv'; | ||
| } | ||
|
|
||
| private createDataChannel(): void { | ||
| if (this._dataChannel || this._dataChannelEnded || !this.config.call.hasFlag('create-data-channel')) { | ||
| return; | ||
|
|
@@ -565,8 +573,8 @@ export class MediaCallWebRTCProcessor implements IWebRTCProcessor { | |
|
|
||
| private getCommandFromDataChannelMessage(message: string): P2PCommand | null { | ||
| try { | ||
| const obj = JSON.parse(message); | ||
| if (obj.command && this.isValidCommand(obj.command)) { | ||
| const obj = JSON.parse(message) as { command?: unknown }; | ||
| if (typeof obj.command === 'string' && this.isValidCommand(obj.command)) { | ||
| return obj.command; | ||
| } | ||
| } catch { | ||
|
|
@@ -632,6 +640,10 @@ export class MediaCallWebRTCProcessor implements IWebRTCProcessor { | |
| return; | ||
| } | ||
|
|
||
| if (!this.inputTrack) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P3: This guard correctly prevents micless calls from being falsely inferred as remote-held, but it also disables remote-held detection entirely once the local input track is absent. Because inputTrack can be cleared mid-call via setInputTrack(null), a call that was correctly marked as remote-held while the mic was present will keep _remoteHeld (exposed as remoteHeld in Call.ts) frozen at true even after the remote resumes, since updateRemoteHeld now returns before re-evaluating the audio transceivers. If stale held state is a concern, consider only skipping when there is genuinely nothing to infer, or explicitly resetting held state when the track is removed. Prompt for AI agents |
||
| return; | ||
| } | ||
|
|
||
| let anyTransceiverNotSending = false; | ||
| const transceivers = this.getTransceivers('audio'); | ||
|
|
||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.