Skip to content

Commit

Permalink
feat: interruption events, background handling
Browse files Browse the repository at this point in the history
  • Loading branch information
amar-1995 authored Jul 31, 2024
1 parent 2147008 commit 2cbb2a0
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 15 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
30 changes: 24 additions & 6 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 @@ -60,7 +59,7 @@ 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);
}
}
Expand All @@ -73,9 +72,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 +250,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
35 changes: 28 additions & 7 deletions packages/hms-video-store/src/media/tracks/HMSLocalVideoTrack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ export class HMSLocalVideoTrack extends HMSVideoTrack {
this.pluginsManager = new HMSVideoPluginsManager(this, eventBus);
this.mediaStreamPluginsManager = new HMSMediaStreamPluginsManager(eventBus, room);
this.setFirstTrackId(this.trackId);
if (isBrowser && isMobile()) {
if (isBrowser && source === 'regular') {
document.addEventListener('visibilitychange', this.handleVisibilityChange);
}
}
Expand Down Expand Up @@ -495,13 +495,34 @@ export class HMSLocalVideoTrack extends HMSVideoTrack {
};

private handleVisibilityChange = async () => {
if (document.visibilityState === 'hidden' && this.source === 'regular') {
this.enabledStateBeforeBackground = this.enabled;
this.nativeTrack.enabled = false;
this.replaceSenderTrack(this.nativeTrack);
if (document.visibilityState === 'hidden') {
if (isMobile()) {
this.enabledStateBeforeBackground = this.enabled;
this.nativeTrack.enabled = false;
HMSLogger.d(this.TAG, 'visibility hidden muting track');
this.replaceSenderTrack(this.nativeTrack);
// started interruption event
this.eventBus.analytics.publish(
this.sendInterruptionEvent({
started: true,
}),
);
}
} else {
this.nativeTrack.enabled = this.enabledStateBeforeBackground;
this.replaceSenderTrack(this.processedTrack || this.nativeTrack);
if (this.nativeTrack.muted || this.nativeTrack.readyState === 'ended') {
HMSLogger.d(this.TAG, 'visibility visible, restarting track', `${this}`);
const track = await this.replaceTrackWith(this.settings);
this.nativeTrack?.stop();
this.nativeTrack = track;
}
if (isMobile()) {
this.nativeTrack.enabled = this.enabledStateBeforeBackground;
await this.replaceSender(this.nativeTrack, this.enabledStateBeforeBackground);
} else {
await this.replaceSender(this.nativeTrack, this.enabled);
}
await this.processPlugins();
this.videoHandler.updateSinks();
}
this.eventBus.localVideoEnabled.publish({ enabled: this.nativeTrack.enabled, track: this });
};
Expand Down
12 changes: 11 additions & 1 deletion packages/hms-video-store/src/media/tracks/HMSTrack.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { HMSTrackType } from './HMSTrackType';
import AnalyticsEventFactory from '../../analytics/AnalyticsEventFactory';
import { stringifyMediaStreamTrack } from '../../utils/json';
import HMSLogger from '../../utils/logger';
import { HMSMediaStream } from '../streams';
Expand Down Expand Up @@ -84,7 +85,16 @@ export abstract class HMSTrack {
protected setFirstTrackId(trackId: string) {
this.firstTrackId = trackId;
}

/**
* @internal
* It will send event to analytics when interruption start/stop
*/
sendInterruptionEvent({ started, isRemoteAudio = false }: { started: boolean; isRemoteAudio?: boolean }) {
return AnalyticsEventFactory.interruption(started, isRemoteAudio ? 'remote.audio' : this.type, {
deviceId: this.nativeTrack.getSettings().deviceId,
groupId: this.nativeTrack.getSettings().groupId,
});
}
/**
* @internal
* take care of -
Expand Down

0 comments on commit 2cbb2a0

Please sign in to comment.