@100mslive/hms-video-store 0.12.37 → 0.12.38-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/dist/index.cjs.js +9 -9
- package/dist/index.cjs.js.map +4 -4
- package/dist/index.js +9 -9
- package/dist/index.js.map +4 -4
- package/dist/media/tracks/HMSLocalAudioTrack.d.ts +1 -0
- package/dist/media/tracks/HMSLocalVideoTrack.d.ts +1 -0
- package/dist/test/setup.d.ts +1 -0
- package/package.json +2 -2
- package/src/analytics/AnalyticsTimer.ts +11 -3
- package/src/media/tracks/HMSLocalAudioTrack.ts +26 -6
- package/src/media/tracks/HMSLocalVideoTrack.ts +27 -8
- package/src/rtc-stats/utils.ts +0 -1
- package/src/test/setup.ts +14 -0
- package/src/utils/track.ts +2 -0
|
@@ -20,6 +20,7 @@ export declare class HMSLocalAudioTrack extends HMSAudioTrack {
|
|
|
20
20
|
* for you to stop, which leads to the microphone not released even after leave is called.
|
|
21
21
|
*/
|
|
22
22
|
private tracksCreated;
|
|
23
|
+
private permissionState?;
|
|
23
24
|
audioLevelMonitor?: TrackAudioLevelMonitor;
|
|
24
25
|
/**
|
|
25
26
|
* see the doc in HMSLocalVideoTrack
|
|
@@ -16,6 +16,7 @@ export declare class HMSLocalVideoTrack extends HMSVideoTrack {
|
|
|
16
16
|
private _layerDefinitions;
|
|
17
17
|
private TAG;
|
|
18
18
|
private enabledStateBeforeBackground;
|
|
19
|
+
private permissionState?;
|
|
19
20
|
/**
|
|
20
21
|
* true if it's screenshare and current tab is what is being shared. Browser dependent, Chromium only
|
|
21
22
|
* at the point of writing this comment.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "0.12.
|
|
2
|
+
"version": "0.12.38-alpha.0",
|
|
3
3
|
"license": "MIT",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
@@ -73,5 +73,5 @@
|
|
|
73
73
|
"conferencing",
|
|
74
74
|
"100ms"
|
|
75
75
|
],
|
|
76
|
-
"gitHead": "
|
|
76
|
+
"gitHead": "37d70e0a4986c804cb8dcc51fecb4ea1c75761dc"
|
|
77
77
|
}
|
|
@@ -31,13 +31,21 @@ export class AnalyticsTimer {
|
|
|
31
31
|
private eventPerformanceMeasures: Partial<Record<TimedEvent, PerformanceMeasure>> = {};
|
|
32
32
|
|
|
33
33
|
start(eventName: TimedEvent) {
|
|
34
|
-
|
|
34
|
+
try {
|
|
35
|
+
if (typeof performance !== 'undefined' && performance.mark) {
|
|
36
|
+
performance.mark(eventName);
|
|
37
|
+
}
|
|
38
|
+
} catch (error) {
|
|
39
|
+
HMSLogger.w('[AnalyticsTimer]', `Error marking performance for event ${eventName}`, { error });
|
|
40
|
+
}
|
|
35
41
|
}
|
|
36
42
|
|
|
37
43
|
end(eventName: TimedEvent) {
|
|
38
44
|
try {
|
|
39
|
-
|
|
40
|
-
|
|
45
|
+
if (typeof performance !== 'undefined' && performance.measure) {
|
|
46
|
+
this.eventPerformanceMeasures[eventName] = performance.measure(eventName, eventName);
|
|
47
|
+
HMSLogger.d('[HMSPerformanceTiming]', eventName, this.eventPerformanceMeasures[eventName]?.duration);
|
|
48
|
+
}
|
|
41
49
|
} catch (error) {
|
|
42
50
|
HMSLogger.w('[AnalyticsTimer]', `Error in measuring performance for event ${eventName}`, { error });
|
|
43
51
|
}
|
|
@@ -2,11 +2,13 @@ import isEqual from 'lodash.isequal';
|
|
|
2
2
|
import { HMSAudioTrack } from './HMSAudioTrack';
|
|
3
3
|
import AnalyticsEventFactory from '../../analytics/AnalyticsEventFactory';
|
|
4
4
|
import { DeviceStorageManager } from '../../device-manager/DeviceStorage';
|
|
5
|
+
import { ErrorCodes } from '../../error/ErrorCodes';
|
|
5
6
|
import { HMSException } from '../../error/HMSException';
|
|
6
7
|
import { EventBus } from '../../events/EventBus';
|
|
7
8
|
import { HMSAudioTrackSettings as IHMSAudioTrackSettings } from '../../interfaces';
|
|
8
9
|
import { HMSAudioPlugin, HMSPluginSupportResult } from '../../plugins';
|
|
9
10
|
import { HMSAudioPluginsManager } from '../../plugins/audio';
|
|
11
|
+
import { LocalTrackManager } from '../../sdk/LocalTrackManager';
|
|
10
12
|
import Room from '../../sdk/models/HMSRoom';
|
|
11
13
|
import HMSLogger from '../../utils/logger';
|
|
12
14
|
import { getAudioTrack, isEmptyTrack, listenToPermissionChange } from '../../utils/track';
|
|
@@ -33,6 +35,7 @@ export class HMSLocalAudioTrack extends HMSAudioTrack {
|
|
|
33
35
|
*/
|
|
34
36
|
private tracksCreated = new Set<MediaStreamTrack>();
|
|
35
37
|
|
|
38
|
+
private permissionState?: PermissionState;
|
|
36
39
|
audioLevelMonitor?: TrackAudioLevelMonitor;
|
|
37
40
|
|
|
38
41
|
/**
|
|
@@ -113,18 +116,22 @@ export class HMSLocalAudioTrack extends HMSAudioTrack {
|
|
|
113
116
|
}),
|
|
114
117
|
);
|
|
115
118
|
} else {
|
|
116
|
-
HMSLogger.d(this.TAG, 'On visibile replacing track as it is not publishing');
|
|
117
|
-
try {
|
|
118
|
-
await this.replaceTrackWith(this.settings);
|
|
119
|
-
} catch (error) {
|
|
120
|
-
this.eventBus.error.publish(error as HMSException);
|
|
121
|
-
}
|
|
122
119
|
this.eventBus.analytics.publish(
|
|
123
120
|
this.sendInterruptionEvent({
|
|
124
121
|
started: false,
|
|
125
122
|
reason: 'visibility-change',
|
|
126
123
|
}),
|
|
127
124
|
);
|
|
125
|
+
if (this.permissionState && this.permissionState !== 'granted') {
|
|
126
|
+
HMSLogger.d(this.TAG, 'On visibile not replacing track as permission is not granted');
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
HMSLogger.d(this.TAG, 'On visibile replacing track as it is not publishing');
|
|
130
|
+
try {
|
|
131
|
+
await this.replaceTrackWith(this.settings);
|
|
132
|
+
} catch (error) {
|
|
133
|
+
this.eventBus.error.publish(error as HMSException);
|
|
134
|
+
}
|
|
128
135
|
}
|
|
129
136
|
};
|
|
130
137
|
|
|
@@ -161,6 +168,18 @@ export class HMSLocalAudioTrack extends HMSAudioTrack {
|
|
|
161
168
|
HMSLogger.d(this.TAG, 'replaceTrack, Previous track stopped', prevTrack, 'newTrack', newTrack);
|
|
162
169
|
await this.updateTrack(newTrack);
|
|
163
170
|
} catch (e) {
|
|
171
|
+
const error = e as HMSException;
|
|
172
|
+
|
|
173
|
+
if (
|
|
174
|
+
error.code === ErrorCodes.TracksErrors.CANT_ACCESS_CAPTURE_DEVICE ||
|
|
175
|
+
error.code === ErrorCodes.TracksErrors.SYSTEM_DENIED_PERMISSION
|
|
176
|
+
) {
|
|
177
|
+
const newTrack = await LocalTrackManager.getEmptyAudioTrack();
|
|
178
|
+
this.addTrackEventListeners(newTrack);
|
|
179
|
+
this.tracksCreated.add(newTrack);
|
|
180
|
+
await this.updateTrack(newTrack);
|
|
181
|
+
throw error;
|
|
182
|
+
}
|
|
164
183
|
// Generate a new track from previous settings so there will be audio because previous track is stopped
|
|
165
184
|
const newTrack = await getAudioTrack(this.settings);
|
|
166
185
|
this.addTrackEventListeners(newTrack);
|
|
@@ -317,6 +336,7 @@ export class HMSLocalAudioTrack extends HMSAudioTrack {
|
|
|
317
336
|
|
|
318
337
|
private trackPermissions = () => {
|
|
319
338
|
listenToPermissionChange('microphone', (state: PermissionState) => {
|
|
339
|
+
this.permissionState = state;
|
|
320
340
|
this.eventBus.analytics.publish(AnalyticsEventFactory.permissionChange(this.type, state));
|
|
321
341
|
if (state === 'denied') {
|
|
322
342
|
this.eventBus.localAudioEnabled.publish({ enabled: false, track: this });
|
|
@@ -3,6 +3,7 @@ import { HMSVideoTrack } from './HMSVideoTrack';
|
|
|
3
3
|
import { VideoElementManager } from './VideoElementManager';
|
|
4
4
|
import AnalyticsEventFactory from '../../analytics/AnalyticsEventFactory';
|
|
5
5
|
import { DeviceStorageManager } from '../../device-manager/DeviceStorage';
|
|
6
|
+
import { ErrorCodes } from '../../error/ErrorCodes';
|
|
6
7
|
import { ErrorFactory } from '../../error/ErrorFactory';
|
|
7
8
|
import { HMSAction } from '../../error/HMSAction';
|
|
8
9
|
import { HMSException } from '../../error/HMSException';
|
|
@@ -40,6 +41,7 @@ export class HMSLocalVideoTrack extends HMSVideoTrack {
|
|
|
40
41
|
private _layerDefinitions: HMSSimulcastLayerDefinition[] = [];
|
|
41
42
|
private TAG = '[HMSLocalVideoTrack]';
|
|
42
43
|
private enabledStateBeforeBackground = false;
|
|
44
|
+
private permissionState?: PermissionState;
|
|
43
45
|
|
|
44
46
|
/**
|
|
45
47
|
* true if it's screenshare and current tab is what is being shared. Browser dependent, Chromium only
|
|
@@ -392,7 +394,20 @@ export class HMSLocalVideoTrack extends HMSVideoTrack {
|
|
|
392
394
|
this.settings = this.buildNewSettings({ deviceId: this.nativeTrack.getSettings().deviceId });
|
|
393
395
|
}
|
|
394
396
|
return newTrack;
|
|
395
|
-
} catch (
|
|
397
|
+
} catch (e) {
|
|
398
|
+
const error = e as HMSException;
|
|
399
|
+
|
|
400
|
+
if (
|
|
401
|
+
error.code === ErrorCodes.TracksErrors.CANT_ACCESS_CAPTURE_DEVICE ||
|
|
402
|
+
error.code === ErrorCodes.TracksErrors.SYSTEM_DENIED_PERMISSION
|
|
403
|
+
) {
|
|
404
|
+
const track = await this.replaceTrackWithBlank();
|
|
405
|
+
this.addTrackEventListeners(track);
|
|
406
|
+
await this.replaceSender(track, this.enabled);
|
|
407
|
+
this.nativeTrack = track;
|
|
408
|
+
this.videoHandler.updateSinks();
|
|
409
|
+
throw error;
|
|
410
|
+
}
|
|
396
411
|
// Generate a new track from previous settings so there won't be blank tile because previous track is stopped
|
|
397
412
|
const track = await getVideoTrack(this.settings);
|
|
398
413
|
this.addTrackEventListeners(track);
|
|
@@ -595,6 +610,17 @@ export class HMSLocalVideoTrack extends HMSVideoTrack {
|
|
|
595
610
|
}),
|
|
596
611
|
);
|
|
597
612
|
} else {
|
|
613
|
+
// ended interruption event
|
|
614
|
+
this.eventBus.analytics.publish(
|
|
615
|
+
this.sendInterruptionEvent({
|
|
616
|
+
started: false,
|
|
617
|
+
reason: 'visibility-change',
|
|
618
|
+
}),
|
|
619
|
+
);
|
|
620
|
+
if (this.permissionState && this.permissionState !== 'granted') {
|
|
621
|
+
HMSLogger.d(this.TAG, 'On visibile not replacing track as permission is not granted');
|
|
622
|
+
return;
|
|
623
|
+
}
|
|
598
624
|
HMSLogger.d(this.TAG, 'visibility visible, restoring track state', this.enabledStateBeforeBackground);
|
|
599
625
|
if (this.enabledStateBeforeBackground) {
|
|
600
626
|
try {
|
|
@@ -603,13 +629,6 @@ export class HMSLocalVideoTrack extends HMSVideoTrack {
|
|
|
603
629
|
this.eventBus.error.publish(error as HMSException);
|
|
604
630
|
}
|
|
605
631
|
}
|
|
606
|
-
// ended interruption event
|
|
607
|
-
this.eventBus.analytics.publish(
|
|
608
|
-
this.sendInterruptionEvent({
|
|
609
|
-
started: false,
|
|
610
|
-
reason: 'visibility-change',
|
|
611
|
-
}),
|
|
612
|
-
);
|
|
613
632
|
}
|
|
614
633
|
};
|
|
615
634
|
}
|
package/src/rtc-stats/utils.ts
CHANGED
|
@@ -189,7 +189,6 @@ export const getActiveCandidatePairFromReport = (report?: RTCStatsReport): RTCIc
|
|
|
189
189
|
report?.forEach(stat => {
|
|
190
190
|
if (stat.type === 'transport') {
|
|
191
191
|
// TS doesn't have correct types for RTCStatsReports
|
|
192
|
-
// @ts-expect-error
|
|
193
192
|
activeCandidatePair = report?.get(stat.selectedCandidatePairId);
|
|
194
193
|
}
|
|
195
194
|
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// Setup for Jest tests
|
|
2
|
+
|
|
3
|
+
// Mock Performance API properly for Jest 29
|
|
4
|
+
global.performance = {
|
|
5
|
+
mark: jest.fn(),
|
|
6
|
+
measure: jest.fn(() => ({ duration: 0 } as PerformanceMeasure)),
|
|
7
|
+
clearMarks: jest.fn(),
|
|
8
|
+
clearMeasures: jest.fn(),
|
|
9
|
+
getEntriesByName: jest.fn(() => []),
|
|
10
|
+
getEntriesByType: jest.fn(() => []),
|
|
11
|
+
now: jest.fn(() => Date.now()),
|
|
12
|
+
} as any;
|
|
13
|
+
|
|
14
|
+
export {};
|
package/src/utils/track.ts
CHANGED
|
@@ -45,7 +45,9 @@ export const listenToPermissionChange = (
|
|
|
45
45
|
// @ts-ignore
|
|
46
46
|
.query({ name: permissionName })
|
|
47
47
|
.then(permission => {
|
|
48
|
+
onChange(permission.state);
|
|
48
49
|
permission.onchange = () => {
|
|
50
|
+
HMSLogger.d(`${permissionName} permission changed`, permission.state);
|
|
49
51
|
onChange(permission.state);
|
|
50
52
|
};
|
|
51
53
|
})
|