Skip to content

Commit

Permalink
fix: update branch
Browse files Browse the repository at this point in the history
  • Loading branch information
KaustubhKumar05 committed Aug 7, 2024
2 parents 2097643 + d67a092 commit 29f537d
Show file tree
Hide file tree
Showing 47 changed files with 722 additions and 441 deletions.
2 changes: 1 addition & 1 deletion examples/prebuilt-react-integration/index.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<!doctype html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
Expand Down
12 changes: 12 additions & 0 deletions packages/hms-video-store/src/analytics/AnalyticsEventFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,18 @@ export default class AnalyticsEventFactory {
level: AnalyticsEventLevel.INFO,
});
}

static interruption(started: boolean, type: string, deviceInfo: Partial<MediaDeviceInfo>) {
return new AnalyticsEvent({
name: `${started ? 'interruption.start' : 'interruption.stop'}`,
level: AnalyticsEventLevel.INFO,
properties: {
type,
...deviceInfo,
},
});
}

private static eventNameFor(name: string, ok: boolean) {
const suffix = ok ? 'success' : 'failed';
return `${name}.${suffix}`;
Expand Down
23 changes: 23 additions & 0 deletions packages/hms-video-store/src/analytics/AnalyticsTransport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,30 @@ export abstract class AnalyticsTransport {
abstract failedEvents: Queue<AnalyticsEvent>;
private readonly TAG = '[AnalyticsTransport]';

private eventCount = 0;
private lastResetTime: number = Date.now();
private readonly MAX_EVENTS_PER_MINUTE: number = 200;
private readonly RESET_INTERVAL_MS: number = 60000;

private checkRateLimit() {
const now = Date.now();
if (now - this.lastResetTime >= this.RESET_INTERVAL_MS) {
this.eventCount = 0;
this.lastResetTime = now;
}
if (this.eventCount >= this.MAX_EVENTS_PER_MINUTE) {
throw new Error('Too many events being sent, please check the implementation.');
}
this.eventCount++;
}

sendEvent(event: AnalyticsEvent) {
try {
this.checkRateLimit();
} catch (e) {
HMSLogger.w(this.TAG, 'Rate limit exceeded', e);
throw e;
}
try {
this.sendSingleEvent(event);
this.flushFailedEvents();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -295,29 +295,15 @@ export class AudioSinkManager {
if ('ondevicechange' in navigator.mediaDevices) {
return;
}
let bluetoothDevice: InputDeviceInfo | null = null;
let speakerPhone: InputDeviceInfo | null = null;
let wired: InputDeviceInfo | null = null;
let earpiece: InputDeviceInfo | null = null;

for (const device of this.deviceManager.audioInput) {
const label = device.label.toLowerCase();
if (label.includes('speakerphone')) {
speakerPhone = device;
} else if (label.includes('wired')) {
wired = device;
} else if (label.includes('bluetooth')) {
bluetoothDevice = device;
} else if (label.includes('earpiece')) {
earpiece = device;
}
}
const { bluetoothDevice, earpiece, speakerPhone, wired } = this.deviceManager.categorizeAudioInputDevices();
const localAudioTrack = this.store.getLocalPeer()?.audioTrack;
if (localAudioTrack && earpiece) {
const externalDeviceID = bluetoothDevice?.deviceId || wired?.deviceId || speakerPhone?.deviceId;
const manualSelection = this.deviceManager.getManuallySelectedAudioDevice();
const externalDeviceID =
manualSelection?.deviceId || bluetoothDevice?.deviceId || wired?.deviceId || speakerPhone?.deviceId;
HMSLogger.d(this.TAG, 'externalDeviceID', externalDeviceID);
// already selected appropriate device
if (localAudioTrack.settings.deviceId === externalDeviceID) {
if (localAudioTrack.settings.deviceId === externalDeviceID && this.earpieceSelected) {
return;
}
if (!this.earpieceSelected) {
Expand Down
8 changes: 7 additions & 1 deletion packages/hms-video-store/src/connection/HMSConnection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ export default abstract class HMSConnection {
* - [HMSSubscribeConnection] clears this list as soon as we call [addIceCandidate]
*/
readonly candidates = new Array<RTCIceCandidateInit>();
// @ts-ignore
private sfuNodeId?: string;

selectedCandidatePair?: RTCIceCandidatePair;

Expand All @@ -48,6 +50,10 @@ export default abstract class HMSConnection {
return this.role === HMSConnectionRole.Publish ? HMSAction.PUBLISH : HMSAction.SUBSCRIBE;
}

setSfuNodeId(nodeId?: string) {
this.sfuNodeId = nodeId;
}

addTransceiver(track: MediaStreamTrack, init: RTCRtpTransceiverInit): RTCRtpTransceiver {
return this.nativeConnection.addTransceiver(track, init);
}
Expand Down Expand Up @@ -198,7 +204,7 @@ export default abstract class HMSConnection {
return await this.nativeConnection.getStats();
}

async close() {
close() {
this.nativeConnection.close();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ export default class HMSPublishConnection extends HMSConnection {
this.observer.onIceConnectionChange(this.nativeConnection.iceConnectionState);
};

// @TODO(eswar): Remove this. Use iceconnectionstate change with interval and threshold.
this.nativeConnection.onconnectionstatechange = () => {
this.observer.onConnectionStateChange(this.nativeConnection.connectionState);

Expand All @@ -51,6 +50,11 @@ export default class HMSPublishConnection extends HMSConnection {
};
}

close() {
super.close();
this.channel.close();
}

initAfterJoin() {
this.nativeConnection.onnegotiationneeded = async () => {
HMSLogger.d(this.TAG, `onnegotiationneeded`);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,8 +154,8 @@ export default class HMSSubscribeConnection extends HMSConnection {
return this.sendMessage(request, id);
}

async close() {
await super.close();
close() {
super.close();
this.apiChannel?.close();
}

Expand Down
44 changes: 37 additions & 7 deletions packages/hms-video-store/src/device-manager/DeviceManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { ErrorFactory } from '../error/ErrorFactory';
import { HMSException } from '../error/HMSException';
import { EventBus } from '../events/EventBus';
import { DeviceMap, HMSDeviceChangeEvent, SelectedDevices } from '../interfaces';
import { isIOS } from '../internal';
import { HMSAudioTrackSettingsBuilder, HMSVideoTrackSettingsBuilder } from '../media/settings';
import { HMSLocalAudioTrack, HMSLocalTrack, HMSLocalVideoTrack } from '../media/tracks';
import { Store } from '../sdk/store';
Expand Down Expand Up @@ -205,7 +206,11 @@ export class DeviceManager implements HMSDeviceManager {
}
const audioDeviceId = this.store.getConfig()?.settings?.audioInputDeviceId;
if (!audioDeviceId && localPeer?.audioTrack) {
await localPeer.audioTrack.setSettings({ deviceId: this.audioInput[0]?.deviceId }, true);
const getInitialDeviceId = () => {
const nonIPhoneDevice = this.audioInput.find(device => !device.label.toLowerCase().includes('iphone'));
return isIOS() && nonIPhoneDevice ? nonIPhoneDevice?.deviceId : this.getNewAudioInputDevice()?.deviceId;
};
await localPeer.audioTrack.setSettings({ deviceId: getInitialDeviceId() }, true);
}
};

Expand All @@ -232,16 +237,12 @@ export class DeviceManager implements HMSDeviceManager {
* @returns {MediaDeviceInfo}
*/
getNewAudioInputDevice() {
const localPeer = this.store.getLocalPeer();
const audioTrack = localPeer?.audioTrack;
const manualSelection = this.audioInput.find(
device => device.deviceId === audioTrack?.getManuallySelectedDeviceId(),
);
const manualSelection = this.getManuallySelectedAudioDevice();
if (manualSelection) {
return manualSelection;
}
// if manually selected device is not available, reset on the track
audioTrack?.resetManuallySelectedDeviceId();
this.store.getLocalPeer()?.audioTrack?.resetManuallySelectedDeviceId();
const defaultDevice = this.audioInput.find(device => device.deviceId === 'default');
if (defaultDevice) {
// Selecting a non-default device so that the deviceId comparision does not give
Expand Down Expand Up @@ -416,6 +417,35 @@ export class DeviceManager implements HMSDeviceManager {
}
};

getManuallySelectedAudioDevice() {
const localPeer = this.store.getLocalPeer();
const audioTrack = localPeer?.audioTrack;
return this.audioInput.find(device => device.deviceId === audioTrack?.getManuallySelectedDeviceId());
}

// specifically used for mweb
categorizeAudioInputDevices() {
let bluetoothDevice: InputDeviceInfo | null = null;
let speakerPhone: InputDeviceInfo | null = null;
let wired: InputDeviceInfo | null = null;
let earpiece: InputDeviceInfo | null = null;

for (const device of this.audioInput) {
const label = device.label.toLowerCase();
if (label.includes('speakerphone')) {
speakerPhone = device;
} else if (label.includes('wired')) {
wired = device;
} else if (/airpods|buds|wireless|bluetooth/gi.test(label)) {
bluetoothDevice = device;
} else if (label.includes('earpiece')) {
earpiece = device;
}
}

return { bluetoothDevice, speakerPhone, wired, earpiece };
}

// eslint-disable-next-line complexity
private getAudioOutputDeviceMatchingInput(inputDevice?: MediaDeviceInfo) {
const blacklist = this.store.getConfig()?.settings?.speakerAutoSelectionBlacklist || [];
Expand Down
7 changes: 1 addition & 6 deletions packages/hms-video-store/src/interfaces/room.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,8 @@ export interface HMSRoom {
description?: string;
max_size?: number;
large_room_optimization?: boolean;
/**
* @alpha
*/
isEffectsEnabled?: boolean;
/**
* @alpha
*/
isVBEnabled?: boolean;
effectsKey?: string;
isHipaaEnabled?: boolean;
isNoiseCancellationEnabled?: boolean;
Expand Down
1 change: 1 addition & 0 deletions packages/hms-video-store/src/interfaces/update-listener.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ export interface HMSUpdateListener extends DeviceChangeListener, SessionStoreLis
onError(error: HMSException): void;
onReconnecting(error: HMSException): void;
onReconnected(): void;
onSFUMigration?: () => void;
onRoleChangeRequest(request: HMSRoleChangeRequest): void;
onRoleUpdate(newRole: string): void;
onChangeTrackStateRequest(request: HMSChangeTrackStateRequest): void;
Expand Down
52 changes: 45 additions & 7 deletions packages/hms-video-store/src/media/tracks/HMSLocalAudioTrack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import { HMSAudioPlugin, HMSPluginSupportResult } from '../../plugins';
import { HMSAudioPluginsManager } from '../../plugins/audio';
import Room from '../../sdk/models/HMSRoom';
import HMSLogger from '../../utils/logger';
import { isBrowser, isIOS } from '../../utils/support';
import { getAudioTrack, isEmptyTrack } from '../../utils/track';
import { TrackAudioLevelMonitor } from '../../utils/track-audio-level-monitor';
import { HMSAudioTrackSettings, HMSAudioTrackSettingsBuilder } from '../settings';
Expand Down Expand Up @@ -47,7 +46,7 @@ export class HMSLocalAudioTrack extends HMSAudioTrack {
source: string,
private eventBus: EventBus,
settings: HMSAudioTrackSettings = new HMSAudioTrackSettingsBuilder().build(),
room?: Room,
private room?: Room,
) {
super(stream, track, source);
stream.tracks.push(this);
Expand All @@ -60,11 +59,31 @@ export class HMSLocalAudioTrack extends HMSAudioTrack {
}
this.pluginsManager = new HMSAudioPluginsManager(this, eventBus, room);
this.setFirstTrackId(track.id);
if (isIOS() && isBrowser) {
if (source === 'regular') {
document.addEventListener('visibilitychange', this.handleVisibilityChange);
}
}

clone(stream: HMSLocalStream) {
const track = new HMSLocalAudioTrack(
stream,
this.nativeTrack.clone(),
this.source!,
this.eventBus,
this.settings,
this.room,
);

if (this.pluginsManager.pluginsMap.size > 0) {
this.pluginsManager.pluginsMap.forEach(value => {
track
.addPlugin(value)
.catch((e: Error) => HMSLogger.e(this.TAG, 'Plugin add failed while migrating', value, e));
});
}
return track;
}

getManuallySelectedDeviceId() {
return this.manuallySelectedDeviceId;
}
Expand All @@ -73,9 +92,30 @@ export class HMSLocalAudioTrack extends HMSAudioTrack {
this.manuallySelectedDeviceId = undefined;
}

private isTrackNotPublishing = () => {
return this.nativeTrack.readyState === 'ended' || this.nativeTrack.muted;
};

private handleVisibilityChange = async () => {
if (document.visibilityState === 'visible') {
// track state is fine do nothing
if (!this.isTrackNotPublishing()) {
HMSLogger.d(this.TAG, `visibiltiy: ${document.visibilityState}`, `${this}`);
return;
}
if (document.visibilityState === 'hidden') {
this.eventBus.analytics.publish(
this.sendInterruptionEvent({
started: true,
}),
);
} else {
HMSLogger.d(this.TAG, 'On visibile replacing track as it is not publishing');
await this.replaceTrackWith(this.settings);
this.eventBus.analytics.publish(
this.sendInterruptionEvent({
started: false,
}),
);
}
};

Expand Down Expand Up @@ -230,9 +270,7 @@ export class HMSLocalAudioTrack extends HMSAudioTrack {
this.processedTrack?.stop();
this.isPublished = false;
this.destroyAudioLevelMonitor();
if (isIOS() && isBrowser) {
document.removeEventListener('visibilitychange', this.handleVisibilityChange);
}
document.removeEventListener('visibilitychange', this.handleVisibilityChange);
}

/**
Expand Down
Loading

0 comments on commit 29f537d

Please sign in to comment.