Skip to content

Commit

Permalink
Fix restartTrack for audio in Safari
Browse files Browse the repository at this point in the history
On Safari we need to stop the current audio device prior to acquiring the new one. Fixes #63
  • Loading branch information
davidzhao committed Oct 26, 2021
1 parent 3ee9b10 commit 2b97b81
Show file tree
Hide file tree
Showing 4 changed files with 23 additions and 13 deletions.
3 changes: 3 additions & 0 deletions src/room/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,8 @@ export enum RoomEvent {

/**
* A track was published successfully
*
* args: ([[LocalTrackPublication]], [[LocalParticipant]])
*/
LocalTrackPublished = 'localTrackPublished',

Expand Down Expand Up @@ -188,6 +190,7 @@ export enum TrackEvent {
Message = 'message',
Muted = 'muted',
Unmuted = 'unmuted',
Ended = 'ended',
/** @internal */
UpdateSettings = 'updateSettings',
/** @internal */
Expand Down
2 changes: 1 addition & 1 deletion src/room/participant/LocalParticipant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ export default class LocalParticipant extends Participant {
// handle track actions
track.on(TrackEvent.Muted, this.onTrackMuted);
track.on(TrackEvent.Unmuted, this.onTrackUnmuted);
track.mediaStreamTrack.addEventListener('ended', () => {
track.on(TrackEvent.Ended, () => {
this.unpublishTrack(track);
});

Expand Down
5 changes: 2 additions & 3 deletions src/room/track/LocalAudioTrack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,8 @@ export default class LocalAudioTrack extends LocalTrack {
return;
}
this.constraints.deviceId = deviceId;
await this.restartTrack();
if (this.isMuted) {
this.mediaStreamTrack.enabled = false;
if (!this.isMuted) {
await this.restartTrack();
}
}

Expand Down
26 changes: 17 additions & 9 deletions src/room/track/LocalTrack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export default class LocalTrack extends Track {
protected constructor(mediaTrack: MediaStreamTrack, kind: Track.Kind,
name?: string, constraints?: MediaTrackConstraints) {
super(mediaTrack, kind, name);
this.mediaStreamTrack.addEventListener('ended', this.handleEnded);
this.constraints = constraints ?? mediaTrack.getConstraints();
}

Expand Down Expand Up @@ -129,19 +130,22 @@ export default class LocalTrack extends Track {
streamConstraints.audio = constraints;
}

// TODO: for safari, there is a bug that might cause this to be wonky
// _workaroundWebKitBug1208516
const mediaStream = await navigator.mediaDevices.getUserMedia(streamConstraints);
const newTrack = mediaStream.getTracks()[0];
log.info('re-acquired MediaStreamTrack');

// detach and reattach
this.mediaStreamTrack.stop();
// detach
this.attachedElements.forEach((el) => {
detachTrack(this.mediaStreamTrack, el);
});
this.mediaStreamTrack.removeEventListener('ended', this.handleEnded);
// on Safari, the old audio track must be stopped before attempting to acquire
// the new track, otherwise the new track will stop with
// 'A MediaStreamTrack ended due to a capture failure`
this.mediaStreamTrack.stop();

// create new track and attach
const mediaStream = await navigator.mediaDevices.getUserMedia(streamConstraints);
const newTrack = mediaStream.getTracks()[0];
newTrack.addEventListener('ended', this.handleEnded);
log.debug('re-acquired MediaStreamTrack');

newTrack.enabled = this.mediaStreamTrack.enabled;
await this.sender.replaceTrack(newTrack);
this.mediaStreamTrack = newTrack;

Expand All @@ -162,4 +166,8 @@ export default class LocalTrack extends Track {
this.mediaStreamTrack.enabled = !muted;
this.emit(muted ? TrackEvent.Muted : TrackEvent.Unmuted, this);
}

private handleEnded = () => {
this.emit(TrackEvent.Ended);
};
}

0 comments on commit 2b97b81

Please sign in to comment.