diff --git a/examples/prebuilt-react-integration/index.html b/examples/prebuilt-react-integration/index.html
index 895cbcd8ce..aee5d151bb 100644
--- a/examples/prebuilt-react-integration/index.html
+++ b/examples/prebuilt-react-integration/index.html
@@ -1,4 +1,4 @@
-
+
diff --git a/packages/hms-video-store/src/analytics/AnalyticsEventFactory.ts b/packages/hms-video-store/src/analytics/AnalyticsEventFactory.ts
index e387fa4991..d7f4200922 100644
--- a/packages/hms-video-store/src/analytics/AnalyticsEventFactory.ts
+++ b/packages/hms-video-store/src/analytics/AnalyticsEventFactory.ts
@@ -256,6 +256,18 @@ export default class AnalyticsEventFactory {
level: AnalyticsEventLevel.INFO,
});
}
+
+ static interruption(started: boolean, type: string, deviceInfo: Partial) {
+ 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}`;
diff --git a/packages/hms-video-store/src/media/tracks/HMSLocalAudioTrack.ts b/packages/hms-video-store/src/media/tracks/HMSLocalAudioTrack.ts
index 2e3883660c..c0e6a99fc6 100644
--- a/packages/hms-video-store/src/media/tracks/HMSLocalAudioTrack.ts
+++ b/packages/hms-video-store/src/media/tracks/HMSLocalAudioTrack.ts
@@ -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';
@@ -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);
}
}
@@ -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,
+ }),
+ );
}
};
@@ -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);
}
/**
diff --git a/packages/hms-video-store/src/media/tracks/HMSLocalVideoTrack.ts b/packages/hms-video-store/src/media/tracks/HMSLocalVideoTrack.ts
index 0a19048514..758881a3d0 100644
--- a/packages/hms-video-store/src/media/tracks/HMSLocalVideoTrack.ts
+++ b/packages/hms-video-store/src/media/tracks/HMSLocalVideoTrack.ts
@@ -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);
}
}
@@ -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 });
};
diff --git a/packages/hms-video-store/src/media/tracks/HMSTrack.ts b/packages/hms-video-store/src/media/tracks/HMSTrack.ts
index b3c5574bb1..470a3eae88 100644
--- a/packages/hms-video-store/src/media/tracks/HMSTrack.ts
+++ b/packages/hms-video-store/src/media/tracks/HMSTrack.ts
@@ -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';
@@ -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 -