Skip to content

Commit 301ccc0

Browse files
authored
Only restart tracks if they are internally managed by the SDK (#279)
* Only restart tracks if they are internally managed by the sdk * changeset * set screen track as managed * change managed naming to isUserProvided * set userProvided in replaceTrack
1 parent b0a5f6a commit 301ccc0

File tree

8 files changed

+42
-17
lines changed

8 files changed

+42
-17
lines changed

.changeset/shiny-eyes-clean.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'livekit-client': patch
3+
---
4+
5+
Only restart tracks if they are internally managed by the sdk

src/room/Room.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -592,7 +592,10 @@ class Room extends (EventEmitter as new () => TypedEmitter<RoomEventCallbacks>)
592592
const track = pub.track!;
593593
this.localParticipant.unpublishTrack(track, false);
594594
if (!track.isMuted) {
595-
if (track instanceof LocalAudioTrack || track instanceof LocalVideoTrack) {
595+
if (
596+
(track instanceof LocalAudioTrack || track instanceof LocalVideoTrack) &&
597+
!track.isUserProvided
598+
) {
596599
// we need to restart the track before publishing, often a full reconnect
597600
// is necessary because computer had gone to sleep.
598601
log.debug('restarting existing track', {

src/room/participant/LocalParticipant.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -367,11 +367,11 @@ export default class LocalParticipant extends Participant {
367367
if (tracks.length === 0) {
368368
throw new TrackInvalidError('no video track found');
369369
}
370-
const screenVideo = new LocalVideoTrack(tracks[0]);
370+
const screenVideo = new LocalVideoTrack(tracks[0], undefined, false);
371371
screenVideo.source = Track.Source.ScreenShare;
372372
const localTracks: Array<LocalTrack> = [screenVideo];
373373
if (stream.getAudioTracks().length > 0) {
374-
const screenAudio = new LocalAudioTrack(stream.getAudioTracks()[0]);
374+
const screenAudio = new LocalAudioTrack(stream.getAudioTracks()[0], undefined, false);
375375
screenAudio.source = Track.Source.ScreenShareAudio;
376376
localTracks.push(screenAudio);
377377
}
@@ -396,10 +396,10 @@ export default class LocalParticipant extends Participant {
396396
if (track instanceof MediaStreamTrack) {
397397
switch (track.kind) {
398398
case 'audio':
399-
track = new LocalAudioTrack(track);
399+
track = new LocalAudioTrack(track, undefined, true);
400400
break;
401401
case 'video':
402-
track = new LocalVideoTrack(track);
402+
track = new LocalVideoTrack(track, undefined, true);
403403
break;
404404
default:
405405
throw new TrackInvalidError(`unsupported MediaStreamTrack kind ${track.kind}`);

src/room/participant/publishUtils.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ export function mediaTrackToLocalTrack(
1818
): LocalVideoTrack | LocalAudioTrack {
1919
switch (mediaStreamTrack.kind) {
2020
case 'audio':
21-
return new LocalAudioTrack(mediaStreamTrack, constraints);
21+
return new LocalAudioTrack(mediaStreamTrack, constraints, false);
2222
case 'video':
23-
return new LocalVideoTrack(mediaStreamTrack, constraints);
23+
return new LocalVideoTrack(mediaStreamTrack, constraints, false);
2424
default:
2525
throw new TrackInvalidError(`unsupported track type: ${mediaStreamTrack.kind}`);
2626
}

src/room/track/LocalAudioTrack.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,12 @@ export default class LocalAudioTrack extends LocalTrack {
1515

1616
private prevStats?: AudioSenderStats;
1717

18-
constructor(mediaTrack: MediaStreamTrack, constraints?: MediaTrackConstraints) {
19-
super(mediaTrack, Track.Kind.Audio, constraints);
18+
constructor(
19+
mediaTrack: MediaStreamTrack,
20+
constraints?: MediaTrackConstraints,
21+
userProvidedTrack = true,
22+
) {
23+
super(mediaTrack, Track.Kind.Audio, constraints, userProvidedTrack);
2024
this.checkForSilence();
2125
}
2226

@@ -42,7 +46,7 @@ export default class LocalAudioTrack extends LocalTrack {
4246
}
4347

4448
async unmute(): Promise<LocalAudioTrack> {
45-
if (this.source === Track.Source.Microphone && this.stopOnMute) {
49+
if (this.source === Track.Source.Microphone && this.stopOnMute && !this.isUserProvided) {
4650
log.debug('reacquiring mic track');
4751
await this.restartTrack();
4852
}

src/room/track/LocalTrack.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,20 @@ export default class LocalTrack extends Track {
1919

2020
protected reacquireTrack: boolean;
2121

22+
protected providedByUser: boolean;
23+
2224
protected constructor(
2325
mediaTrack: MediaStreamTrack,
2426
kind: Track.Kind,
2527
constraints?: MediaTrackConstraints,
28+
userProvidedTrack = false,
2629
) {
2730
super(mediaTrack, kind);
2831
this._mediaStreamTrack.addEventListener('ended', this.handleEnded);
2932
this.constraints = constraints ?? mediaTrack.getConstraints();
3033
this.reacquireTrack = false;
3134
this.wasMuted = false;
35+
this.providedByUser = userProvidedTrack;
3236
}
3337

3438
get id(): string {
@@ -56,6 +60,10 @@ export default class LocalTrack extends Track {
5660
return this._isUpstreamPaused;
5761
}
5862

63+
get isUserProvided() {
64+
return this.providedByUser;
65+
}
66+
5967
/**
6068
* @returns DeviceID of the device that is currently being used for this track
6169
*/
@@ -80,7 +88,7 @@ export default class LocalTrack extends Track {
8088
return this;
8189
}
8290

83-
async replaceTrack(track: MediaStreamTrack): Promise<LocalTrack> {
91+
async replaceTrack(track: MediaStreamTrack, userProvidedTrack = true): Promise<LocalTrack> {
8492
if (!this.sender) {
8593
throw new TrackInvalidError('unable to replace an unpublished track');
8694
}
@@ -108,6 +116,7 @@ export default class LocalTrack extends Track {
108116
});
109117

110118
this.mediaStream = new MediaStream([track]);
119+
this.providedByUser = userProvidedTrack;
111120
return this;
112121
}
113122

@@ -184,7 +193,7 @@ export default class LocalTrack extends Track {
184193
if (!isMobile()) return;
185194
log.debug(`visibility changed, is in Background: ${this.isInBackground}`);
186195

187-
if (!this.isInBackground && this.needsReAcquisition) {
196+
if (!this.isInBackground && this.needsReAcquisition && !this.isUserProvided) {
188197
log.debug(`track needs to be reaquired, restarting ${this.source}`);
189198
await this.restart();
190199
this.reacquireTrack = false;

src/room/track/LocalVideoTrack.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,12 @@ export default class LocalVideoTrack extends LocalTrack {
4141

4242
private subscribedCodecs?: SubscribedCodec[];
4343

44-
constructor(mediaTrack: MediaStreamTrack, constraints?: MediaTrackConstraints) {
45-
super(mediaTrack, Track.Kind.Video, constraints);
44+
constructor(
45+
mediaTrack: MediaStreamTrack,
46+
constraints?: MediaTrackConstraints,
47+
userProvidedTrack = true,
48+
) {
49+
super(mediaTrack, Track.Kind.Video, constraints, userProvidedTrack);
4650
}
4751

4852
get isSimulcast(): boolean {
@@ -92,7 +96,7 @@ export default class LocalVideoTrack extends LocalTrack {
9296
}
9397

9498
async unmute(): Promise<LocalVideoTrack> {
95-
if (this.source === Track.Source.Camera) {
99+
if (this.source === Track.Source.Camera && !this.isUserProvided) {
96100
log.debug('reacquiring camera track');
97101
await this.restartTrack();
98102
}

src/room/track/create.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,11 +110,11 @@ export async function createLocalScreenTracks(
110110
if (tracks.length === 0) {
111111
throw new TrackInvalidError('no video track found');
112112
}
113-
const screenVideo = new LocalVideoTrack(tracks[0]);
113+
const screenVideo = new LocalVideoTrack(tracks[0], undefined, false);
114114
screenVideo.source = Track.Source.ScreenShare;
115115
const localTracks: Array<LocalTrack> = [screenVideo];
116116
if (stream.getAudioTracks().length > 0) {
117-
const screenAudio = new LocalAudioTrack(stream.getAudioTracks()[0]);
117+
const screenAudio = new LocalAudioTrack(stream.getAudioTracks()[0], undefined, false);
118118
screenAudio.source = Track.Source.ScreenShareAudio;
119119
localTracks.push(screenAudio);
120120
}

0 commit comments

Comments
 (0)