Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 21 additions & 1 deletion packages/core/src/types/videoRoomDevice.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
export type CameraUpdated = 'camera.updated'
export type CameraConstraintsUpdated = 'camera.constraints.updated'
export type CameraDisconnected = 'camera.disconnected'
export type MicrophoneUpdated = 'microphone.updated'
export type MicrophoneConstraintsUpdated = 'microphone.constraints.updated'
export type MicrophoneDisconnected = 'microphone.disconnected'
export type SpeakerUpdated = 'speaker.updated'
export type SpeakerDisconnected = 'speaker.disconnected'
Expand All @@ -14,17 +16,22 @@ export type VideoRoomDeviceUpdatedEventNames =
| MicrophoneUpdated
| SpeakerUpdated

export type VideoRoomDeviceConstraintsUpdatedEventNames =
| CameraConstraintsUpdated
| MicrophoneConstraintsUpdated

export type VideoRoomDeviceDisconnectedEventNames =
| CameraDisconnected
| MicrophoneDisconnected
| SpeakerDisconnected

export type VideoRoomDeviceEventNames =
| VideoRoomDeviceUpdatedEventNames
| VideoRoomDeviceConstraintsUpdatedEventNames
| VideoRoomDeviceDisconnectedEventNames

export interface VideoRoomMediaDeviceInfo {
deviceId: MediaDeviceInfo['deviceId'] | undefined
deviceId: MediaTrackConstraintSet['deviceId']
label: MediaDeviceInfo['label'] | undefined
}

Expand All @@ -33,8 +40,21 @@ export interface DeviceUpdatedEventParams {
current: VideoRoomMediaDeviceInfo
}

export interface MediaDeviceIdentifiers {
deviceId: MediaTrackConstraintSet['deviceId']
kind: string
label: string
}
export interface DeviceConstraintsUpdatedEventParams {
kind: string
previous: MediaDeviceIdentifiers | undefined
current: MediaDeviceIdentifiers
constraints: MediaTrackConstraints
}

export type DeviceDisconnectedEventParams = VideoRoomMediaDeviceInfo

export type VideoRoomDeviceEventParams =
| DeviceUpdatedEventParams
| DeviceDisconnectedEventParams
| DeviceConstraintsUpdatedEventParams
64 changes: 54 additions & 10 deletions packages/webrtc/src/BaseConnection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,19 @@ import {
UpdateMediaParams,
UpdateMediaDirection,
} from '@signalwire/core'
import type { ReduxComponent, VertoModifyResponse } from '@signalwire/core'
import type {
ReduxComponent,
VertoModifyResponse,
VideoRoomDeviceConstraintsUpdatedEventNames,
} from '@signalwire/core'
import RTCPeer from './RTCPeer'
import {
ConnectionOptions,
EmitDeviceUpdatedEventsParams,
UpdateMediaOptionsParams,
BaseConnectionEvents,
OnVertoByeParams,
EmitDeviceConstraintsUpdatedEventsParams,
} from './utils/interfaces'
import { stopTrack, getUserMedia, streamIsValid } from './utils'
import {
Expand Down Expand Up @@ -563,11 +568,30 @@ export class BaseConnection<
// Add or update the transceiver (may trigger renegotiation)
await this.handleTransceiverForTrack(newTrack)

// Emit the device.updated events
this.emitDeviceUpdatedEvents({
newTrack,
prevAudioTrack,
prevVideoTrack,
const prevTrack = newTrack.kind === 'audio' ?
prevAudioTrack: prevVideoTrack

if (newTrack.getConstraints().deviceId !== prevTrack?.getConstraints().deviceId) {
// Emit the device.updated events only when the device was updated
this.emitDeviceUpdatedEvents({
newTrack,
prevAudioTrack,
prevVideoTrack,
})
}

this.emitDeviceConstraintsUpdatedEvents({
currentConstraints: newTrack.getConstraints(),
prevTrackIdentifiers: prevTrack ? {
kind: prevTrack?.kind,
label: prevTrack?.label,
deviceId: prevTrack?.getConstraints().deviceId
} : undefined,
currentTrackIdentifiers: {
kind: newTrack.kind,
label: newTrack.label,
deviceId: newTrack.getConstraints().deviceId
}
})
}

Expand Down Expand Up @@ -696,28 +720,48 @@ export class BaseConnection<
if (newTrack.kind === 'audio') {
this.emit('microphone.updated', {
previous: {
deviceId: prevAudioTrack?.id,
// https://developer.mozilla.org/en-US/docs/Web/API/MediaStreamTrack/id
deviceId: prevAudioTrack?.getConstraints().deviceId,
label: prevAudioTrack?.label,
},
current: {
deviceId: newTrack.id,
deviceId: newTrack.getConstraints().deviceId,
label: newTrack.label,
},
})
} else if (newTrack.kind === 'video') {
this.emit('camera.updated', {
previous: {
deviceId: prevVideoTrack?.id,
deviceId: prevVideoTrack?.getConstraints().deviceId,
label: prevVideoTrack?.label,
},
current: {
deviceId: newTrack.id,
deviceId: newTrack.getConstraints().deviceId,
label: newTrack.label,
},
})
}
}

//** internal */
public emitDeviceConstraintsUpdatedEvents({
currentConstraints,
prevTrackIdentifiers,
currentTrackIdentifiers,
}: EmitDeviceConstraintsUpdatedEventsParams) {

const eventPrefix =
currentTrackIdentifiers.kind === 'audioinput' ? 'microphone' : 'camera'
const event: VideoRoomDeviceConstraintsUpdatedEventNames = `${eventPrefix}.constraints.updated`

this.emit(event, {
kind: currentTrackIdentifiers.kind,
previous: prevTrackIdentifiers,
current: currentTrackIdentifiers,
constraints: currentConstraints,
})
}

/**
* Applies the given constraints by retrieving a new stream and then uses
* {@link updateStream} to synchronize local tracks with that new stream.
Expand Down
41 changes: 25 additions & 16 deletions packages/webrtc/src/RTCPeer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -368,30 +368,39 @@ export default class RTCPeer<EventTypes extends EventEmitter.ValidEventTypes> {
try {
const sender = this._getSenderByKind(kind)
if (!sender || !sender.track) {
return this.logger.info(
'No sender to apply constraints',
// TODO this is breaking chance we need to eval if we want to have it on VideoSDK
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// TODO this is breaking chance we need to eval if we want to have it on VideoSDK
// TODO: this is a breaking change. We need to evaluate if we want to have it on VideoSDK

this.logger.error(
'No sender track to apply constraints',
kind,
constraints
)
throw new Error('No sender track to apply constraints')
}
if (sender.track.readyState === 'live') {
const newConstraints: MediaTrackConstraints = {
...sender.track.getConstraints(),
...constraints,
}
const deviceId = this.getDeviceId(kind)
if (deviceId && !this.options.screenShare) {
newConstraints.deviceId = { exact: deviceId }
}
this.logger.info(
`Apply ${kind} constraints`,
this.call.id,
newConstraints
if (sender.track.readyState !== 'live') {
this.logger.error(
'Sender track is not live to apply constraints',
kind,
constraints
)
await sender.track.applyConstraints(newConstraints)
throw new Error('Sender track is not live to apply constraints')
}
const newConstraints: MediaTrackConstraints = {
...sender.track.getConstraints(),
...constraints,
}
const deviceId = this.getDeviceId(kind)
if (deviceId && !this.options.screenShare) {
newConstraints.deviceId = { exact: deviceId }
}
this.logger.info(
`Apply ${kind} constraints`,
this.call.id,
newConstraints
)
await sender.track.applyConstraints(newConstraints)
} catch (error) {
this.logger.error('Error applying constraints', kind, constraints)
throw error
}
}

Expand Down
19 changes: 18 additions & 1 deletion packages/webrtc/src/utils/interfaces.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import type { VideoPositions } from '@signalwire/core'
import type {
EventEmitter,
MediaDeviceIdentifiers,
VideoPositions,
} from '@signalwire/core'
import {
BaseConnectionState,
VideoRoomDeviceEventParams,
Expand Down Expand Up @@ -107,6 +111,19 @@ export interface EmitDeviceUpdatedEventsParams {
prevAudioTrack?: MediaStreamTrack | null
prevVideoTrack?: MediaStreamTrack | null
}
export interface EmitDeviceConstraintsUpdatedEventsParams {
currentConstraints: MediaTrackConstraints
prevTrackIdentifiers: MediaDeviceIdentifiers | undefined
currentTrackIdentifiers: MediaDeviceIdentifiers
}

export interface EmitDeviceUpdatedEventHelperParams
extends EmitDeviceUpdatedEventsParams {
emitFn: <E extends EventEmitter.EventNames<BaseConnectionEvents>>(
event: E,
...args: EventEmitter.EventArgs<BaseConnectionEvents, E>
) => boolean
}

export type UpdateMediaOptionsParams = Pick<
ConnectionOptions,
Expand Down
51 changes: 47 additions & 4 deletions packages/webrtc/src/workers/vertoEventWorker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
} from '@signalwire/core'

import { BaseConnection } from '../BaseConnection'
import { emitDeviceUpdatedEventHelper } from '../utils/helpers'

type VertoEventWorkerOnDone = (args: BaseConnection<any>) => void
type VertoEventWorkerOnFail = (args: { error: Error }) => void
Expand Down Expand Up @@ -129,11 +130,55 @@ export const vertoEventWorker: SDKWorker<
break
}
const { audio, video } = params.mediaParams

const prevAudioTrack = peer?.localAudioTrack?.clone()
if (peer && video) {
peer.applyMediaConstraints('video', video)
const prevTrackIdentifiers = peer?.localVideoTrack
? {
kind: peer.localVideoTrack.kind,
label: peer.localVideoTrack.label,
deviceId: peer.localVideoTrack.getConstraints().deviceId,
}
: undefined

peer
.applyMediaConstraints('video', video)
.then(() => {
instance.emitDeviceConstraintsUpdatedEvents({
currentConstraints: peer.localVideoTrack!.getConstraints(),
prevTrackIdentifiers,
currentTrackIdentifiers: {
kind: peer.localVideoTrack!.kind,
label: peer.localVideoTrack!.label,
deviceId: peer.localVideoTrack!.getConstraints().deviceId,
},
})
})
.catch(console.error)
}
if (peer && audio) {
peer.applyMediaConstraints('audio', audio)
const prevTrackIdentifiers = peer?.localAudioTrack
? {
kind: peer.localAudioTrack.kind,
label: peer.localAudioTrack.label,
deviceId: peer.localAudioTrack.getConstraints().deviceId,
}
: undefined

peer
.applyMediaConstraints('audio', audio)
.then(() => {
instance.emitDeviceConstraintsUpdatedEvents({
currentConstraints: peer.localAudioTrack!.getConstraints(),
prevTrackIdentifiers,
currentTrackIdentifiers: {
kind: peer.localAudioTrack!.kind,
label: peer.localAudioTrack!.label,
deviceId: peer.localAudioTrack!.getConstraints().deviceId,
},
})
})
.catch(console.error)
}
break
}
Expand Down Expand Up @@ -164,6 +209,4 @@ export const vertoEventWorker: SDKWorker<
})
yield sagaEffects.fork(catchableWorker, action)
}

getLogger().trace('vertoEventWorker ended')
}
Loading