@livedigital/client 1.7.0 → 1.10.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.
Files changed (37) hide show
  1. package/dist/constants/events.d.ts +1 -0
  2. package/dist/engine/Peer.d.ts +16 -35
  3. package/dist/engine/PeerProducer.d.ts +2 -1
  4. package/dist/engine/index.d.ts +15 -11
  5. package/dist/engine/media/Consumer.d.ts +0 -1
  6. package/dist/engine/media/VideoConsumer.d.ts +1 -9
  7. package/dist/engine/media/index.d.ts +9 -11
  8. package/dist/engine/media/tracks/AudioTrack.d.ts +9 -0
  9. package/dist/engine/media/tracks/BaseTrack.d.ts +23 -0
  10. package/dist/engine/media/tracks/TrackWithCodecOptions.d.ts +4 -0
  11. package/dist/engine/media/tracks/TrackWithEncodings.d.ts +4 -0
  12. package/dist/engine/media/tracks/VideoTrack.d.ts +13 -0
  13. package/dist/engine/network/LoadBalancerClient.d.ts +7 -1
  14. package/dist/engine/network/index.d.ts +5 -2
  15. package/dist/engine/system/index.d.ts +10 -19
  16. package/dist/index.d.ts +16 -22
  17. package/dist/index.es.js +15 -1
  18. package/dist/index.js +15 -1
  19. package/dist/types/common.d.ts +57 -7
  20. package/package.json +11 -7
  21. package/src/constants/events.ts +1 -0
  22. package/src/engine/Peer.ts +132 -337
  23. package/src/engine/PeerProducer.ts +8 -2
  24. package/src/engine/index.ts +172 -197
  25. package/src/engine/media/Consumer.ts +0 -4
  26. package/src/engine/media/VideoConsumer.ts +1 -18
  27. package/src/engine/media/index.ts +35 -35
  28. package/src/engine/media/tracks/AudioTrack.ts +18 -0
  29. package/src/engine/media/tracks/BaseTrack.ts +70 -0
  30. package/src/engine/media/tracks/TrackWithCodecOptions.ts +5 -0
  31. package/src/engine/media/tracks/TrackWithEncodings.ts +5 -0
  32. package/src/engine/media/tracks/VideoTrack.ts +29 -0
  33. package/src/engine/network/LoadBalancerClient.ts +18 -4
  34. package/src/engine/network/index.ts +8 -3
  35. package/src/engine/system/index.ts +64 -198
  36. package/src/index.ts +39 -68
  37. package/src/types/common.ts +71 -8
@@ -0,0 +1,70 @@
1
+ import { Producer } from 'mediasoup-client/lib/Producer';
2
+ import { MediaKind } from 'mediasoup-client/lib/RtpParameters';
3
+ import { EncoderConfig, TrackLabel } from 'types/common';
4
+
5
+ class BaseTrack {
6
+ readonly #mediaStreamTrack: MediaStreamTrack;
7
+
8
+ protected encoderConfig: EncoderConfig = {};
9
+
10
+ private producer?: Producer;
11
+
12
+ private label: TrackLabel = TrackLabel.Unknown;
13
+
14
+ constructor(mediaStreamTrack: MediaStreamTrack) {
15
+ this.#mediaStreamTrack = mediaStreamTrack;
16
+ }
17
+
18
+ get mediaStreamTrack(): MediaStreamTrack {
19
+ return this.#mediaStreamTrack;
20
+ }
21
+
22
+ get id(): string {
23
+ return this.mediaStreamTrack.id;
24
+ }
25
+
26
+ get kind(): MediaKind {
27
+ return this.mediaStreamTrack.kind as MediaKind;
28
+ }
29
+
30
+ get producerId(): string | undefined {
31
+ return this.producer?.id;
32
+ }
33
+
34
+ get isPublished(): boolean {
35
+ return this.producer
36
+ ? !this.producer.closed
37
+ : false;
38
+ }
39
+
40
+ getLabel(): TrackLabel {
41
+ return this.label;
42
+ }
43
+
44
+ setLabel(label: TrackLabel): void {
45
+ this.label = label;
46
+ }
47
+
48
+ setEncoderConfig(encoderConfig: EncoderConfig): void {
49
+ this.encoderConfig = encoderConfig;
50
+ }
51
+
52
+ getEncoderConfig(): EncoderConfig {
53
+ return this.encoderConfig;
54
+ }
55
+
56
+ setProducer(producer: Producer): void {
57
+ this.producer = producer;
58
+ }
59
+
60
+ getProducer(): Producer | undefined {
61
+ return this.producer;
62
+ }
63
+
64
+ closeProducer(): void {
65
+ this.producer?.close();
66
+ this.producer = undefined;
67
+ }
68
+ }
69
+
70
+ export default BaseTrack;
@@ -0,0 +1,5 @@
1
+ import { ProducerCodecOptions } from 'mediasoup-client/lib/Producer';
2
+
3
+ export default interface TrackWithCodecOptions {
4
+ getCodecOptions(): ProducerCodecOptions;
5
+ }
@@ -0,0 +1,5 @@
1
+ import { RtpEncodingParameters } from 'mediasoup-client/lib/RtpParameters';
2
+
3
+ export default interface TrackWithEncodings {
4
+ getEncodings(): RtpEncodingParameters[];
5
+ }
@@ -0,0 +1,29 @@
1
+ import { WEBCAM_SIMULCAST_ENCODINGS } from 'constants/simulcastEncodings';
2
+ import { ProducerCodecOptions } from 'mediasoup-client/lib/Producer';
3
+ import { RtpEncodingParameters } from 'mediasoup-client/lib/RtpParameters';
4
+ import { VideoCodec, VideoEncoderConfig } from 'types/common';
5
+ import BaseTrack from './BaseTrack';
6
+ import TrackWithCodecOptions from './TrackWithCodecOptions';
7
+ import TrackWithEncodings from './TrackWithEncodings';
8
+
9
+ class VideoTrack extends BaseTrack implements TrackWithCodecOptions, TrackWithEncodings {
10
+ getEncoderConfig(): VideoEncoderConfig {
11
+ return this.encoderConfig;
12
+ }
13
+
14
+ getCodecOptions(): ProducerCodecOptions {
15
+ return {
16
+ videoGoogleStartBitrate: this.getEncoderConfig().videoGoogleStartBitrate || 1000,
17
+ };
18
+ }
19
+
20
+ getPreferredCodec(): VideoCodec {
21
+ return this.getEncoderConfig().preferredCodec || 'h264';
22
+ }
23
+
24
+ getEncodings(): RtpEncodingParameters[] {
25
+ return this.getEncoderConfig().encodings || WEBCAM_SIMULCAST_ENCODINGS;
26
+ }
27
+ }
28
+
29
+ export default VideoTrack;
@@ -2,19 +2,33 @@ import axios, { AxiosInstance } from 'axios';
2
2
  import qs from 'qs';
3
3
  import { GetNodeResponse } from '../../types/common';
4
4
 
5
+ export type LoadBalancerApiClientParams = {
6
+ baseURL?: string;
7
+ timeout?: number;
8
+ customNode?: GetNodeResponse;
9
+ };
10
+
5
11
  class LoadBalancerApiClient {
6
12
  private readonly api: AxiosInstance;
7
13
 
8
- constructor() {
14
+ private customNode?: GetNodeResponse;
15
+
16
+ constructor(params: LoadBalancerApiClientParams) {
17
+ const { baseURL, timeout, customNode } = params;
9
18
  this.api = axios.create({
10
- baseURL: process.env.LIVEDIGITAL_APP_LOAD_BALANCER_BASE_URL,
11
- timeout: 5000,
19
+ baseURL: baseURL || process.env.LIVEDIGITAL_APP_LOAD_BALANCER_BASE_URL,
20
+ timeout: timeout || 5000,
12
21
  withCredentials: false,
13
- paramsSerializer: (params) => qs.stringify(params),
22
+ paramsSerializer: (data) => qs.stringify(data),
14
23
  });
24
+ this.customNode = customNode;
15
25
  }
16
26
 
17
27
  async getNode({ channelId }: { channelId: string }): Promise<GetNodeResponse> {
28
+ if (this.customNode) {
29
+ return this.customNode;
30
+ }
31
+
18
32
  const { data } = await this.api.get<GetNodeResponse>('/nodes/best', {
19
33
  params: { channelId },
20
34
  });
@@ -7,10 +7,14 @@ import {
7
7
  import { Device } from 'mediasoup-client';
8
8
  import SocketIO from './Socket';
9
9
  import { ProduceParams } from '../../types/common';
10
- import LoadBalancerApiClient from './LoadBalancerClient';
10
+ import LoadBalancerApiClient, { LoadBalancerApiClientParams } from './LoadBalancerClient';
11
11
  import { MEDIASOUP_EVENTS, MEDIASOUP_TRANSPORT_EVENTS } from '../../constants/events';
12
12
  import Logger from '../Logger';
13
13
 
14
+ export type NetworkParams = {
15
+ loadbalancer: LoadBalancerApiClientParams,
16
+ };
17
+
14
18
  class Network {
15
19
  public readonly socket: SocketIO;
16
20
 
@@ -22,9 +26,10 @@ class Network {
22
26
 
23
27
  private readonly logger: Logger;
24
28
 
25
- constructor() {
29
+ constructor(params: NetworkParams) {
30
+ const { loadbalancer } = params;
26
31
  this.socket = new SocketIO();
27
- this.loadBalancerClient = new LoadBalancerApiClient();
32
+ this.loadBalancerClient = new LoadBalancerApiClient(loadbalancer);
28
33
  this.logger = new Logger('Network');
29
34
  }
30
35
 
@@ -1,29 +1,32 @@
1
- import { VIDEO_CONSTRAINS } from '../../constants/videoConstrains';
2
- import { AudioTrackConstraints, VideoTrackConstraints } from '../../types/common';
1
+ import { CLIENT_EVENTS } from 'constants/events';
2
+ import EnhancedEventEmitter from 'EnhancedEventEmitter';
3
+ import { AvailableMediaDevices } from 'types/common';
3
4
  import Logger from '../Logger';
4
5
 
6
+ type SystemParams = {
7
+ clientEventEmitter: EnhancedEventEmitter,
8
+ };
9
+
5
10
  class System {
6
11
  public isEnableVideoDevicesLock = false;
7
12
 
8
13
  public isEnableAudioDevicesLock = false;
9
14
 
10
- public isDevicesLoaded = false;
11
-
12
- public videoStream?: MediaStream;
13
-
14
- public audioStream?: MediaStream;
15
+ public isDevicesDetected = false;
15
16
 
16
17
  public availableVideoDevices: MediaDeviceInfo[] = [];
17
18
 
18
19
  public availableAudioDevices: MediaDeviceInfo[] = [];
19
20
 
20
- public currentAudioDeviceId?: string;
21
+ private isMediaDevicesAccessGranted = false;
21
22
 
22
- public currentVideoDeviceId?: string;
23
+ public clientEventEmitter: EnhancedEventEmitter;
23
24
 
24
25
  private readonly logger: Logger;
25
26
 
26
- constructor() {
27
+ constructor(params: SystemParams) {
28
+ const { clientEventEmitter } = params;
29
+ this.clientEventEmitter = clientEventEmitter;
27
30
  this.logger = new Logger('System');
28
31
  this.listenDevices();
29
32
  }
@@ -36,24 +39,6 @@ class System {
36
39
  this.isEnableAudioDevicesLock = value;
37
40
  }
38
41
 
39
- setCurrentVideoDevice(deviceId: string): void {
40
- const isExistsDevice = this.availableVideoDevices.find((device) => device.deviceId === deviceId);
41
- if (!isExistsDevice) {
42
- throw new Error('Unknown video device id');
43
- }
44
-
45
- this.currentVideoDeviceId = deviceId;
46
- }
47
-
48
- setCurrentAudioDevice(deviceId: string): void {
49
- const isExistsDevice = this.availableAudioDevices.find((device) => device.deviceId === deviceId);
50
- if (!isExistsDevice) {
51
- throw new Error('Unknown audio device id');
52
- }
53
-
54
- this.currentAudioDeviceId = deviceId;
55
- }
56
-
57
42
  setAvailableVideoDevices(availableVideoDevices: MediaDeviceInfo[]): void {
58
43
  this.availableVideoDevices = availableVideoDevices;
59
44
  }
@@ -62,199 +47,80 @@ class System {
62
47
  this.availableAudioDevices = availableAudioDevices;
63
48
  }
64
49
 
65
- getVideoConstraints(videoTrackConstraints?: VideoTrackConstraints): MediaTrackConstraints {
66
- const constraints = {
67
- ...VIDEO_CONSTRAINS.hd,
68
- deviceId: this.currentVideoDeviceId || undefined,
69
- frameRate: 15,
70
- };
71
-
72
- if (!videoTrackConstraints) {
73
- return constraints;
74
- }
75
-
76
- return {
77
- ...constraints,
78
- ...videoTrackConstraints,
79
- };
80
- }
81
-
82
- getAudioConstraints(audioTrackConstraints?: AudioTrackConstraints): MediaTrackConstraints {
83
- const constraints = {
84
- autoGainControl: true,
85
- deviceId: this.currentAudioDeviceId || undefined,
86
- };
87
-
88
- if (!audioTrackConstraints) {
89
- return constraints;
90
- }
91
-
92
- return {
93
- ...constraints,
94
- ...audioTrackConstraints,
95
- };
96
- }
97
-
98
- async getVideoTrack(): Promise<MediaStreamTrack> {
99
- const videoStream = this.videoStream || await this.startVideoStream();
100
- const [track] = videoStream.getVideoTracks();
101
- return track;
102
- }
103
-
104
- async getAudioTrack(): Promise<MediaStreamTrack> {
105
- const videoStream = this.videoStream || await this.startAudioStream();
106
- const [track] = videoStream.getAudioTracks();
107
- return track;
108
- }
109
-
110
- async startVideoStream(videoTrackConstraints?: VideoTrackConstraints): Promise<MediaStream> {
111
- if (!this.videoStream || !this.videoStream.active) {
112
- try {
113
- this.videoStream = await navigator.mediaDevices.getUserMedia({
114
- video: this.getVideoConstraints(videoTrackConstraints),
115
- });
116
- this.logger.debug('startVideoStream()');
117
- } catch (error) {
118
- this.logger.error('startVideoStream()', { error });
119
-
120
- if (error.name === 'NotReadableError') {
121
- this.videoStream = undefined;
122
- throw new Error('DeviceIsBusy');
123
- }
124
-
125
- if (error.name === 'This action is not allowed') {
126
- throw new Error('NotAllowedError');
127
- }
128
-
129
- throw new Error('Can`t start video stream');
50
+ async requestMediaDevicesAccess(): Promise<void> {
51
+ try {
52
+ const stream = await navigator.mediaDevices.getUserMedia({
53
+ video: true,
54
+ audio: true,
55
+ });
56
+ stream.getTracks().forEach((track) => track.stop());
57
+ this.isMediaDevicesAccessGranted = true;
58
+ } catch (error) {
59
+ this.logger.error('getUserMedia()', { error });
60
+ if (error.name === 'NotReadableError') {
61
+ throw new Error('DeviceIsBusy');
130
62
  }
131
63
  }
132
-
133
- return this.videoStream;
134
64
  }
135
65
 
136
- async startAudioStream(audioTrackConstraints?: AudioTrackConstraints): Promise<MediaStream> {
137
- if (!this.audioStream || !this.audioStream.active) {
138
- try {
139
- this.audioStream = await navigator.mediaDevices.getUserMedia({
140
- audio: this.getAudioConstraints(audioTrackConstraints),
141
- });
142
- this.logger.debug('startAudioStream()');
143
- } catch (error) {
144
- this.logger.error('startAudioStream()', { error });
145
-
146
- if (error.name === 'NotReadableError') {
147
- this.audioStream = undefined;
148
- throw new Error('DeviceIsBusy');
149
- }
150
-
151
- if (error.name === 'NotAllowedError') {
152
- throw new Error('Device access denied');
153
- }
154
-
155
- throw new Error('Can`t start audio stream');
66
+ async refreshAvailableMediaDevicesList(): Promise<void> {
67
+ const devices = await navigator.mediaDevices.enumerateDevices();
68
+ const videoDevices = [] as MediaDeviceInfo[];
69
+ const audioDevices = [] as MediaDeviceInfo[];
70
+ devices.forEach((device) => {
71
+ if (device.deviceId === '') {
72
+ return;
156
73
  }
157
- }
158
-
159
- return this.audioStream;
160
- }
161
-
162
- async detectDevices(): Promise<void> {
163
- this.isDevicesLoaded = false;
164
74
 
165
- try {
166
- const mediaDevices = await navigator.mediaDevices.enumerateDevices();
167
-
168
- const availableDevicesTypes = {
169
- video: !!mediaDevices.find((device) => device.kind === 'videoinput'),
170
- audio: !!mediaDevices.find((device) => device.kind === 'audioinput'),
171
- };
172
-
173
- try {
174
- await navigator.mediaDevices.getUserMedia({
175
- video: availableDevicesTypes.video && this.getVideoConstraints(),
176
- audio: availableDevicesTypes.audio && this.getAudioConstraints(),
177
- });
178
- } catch (error) {
179
- this.logger.error('getUserMedia()', { error });
180
- if (error.name === 'NotReadableError') {
181
- throw new Error('DeviceIsBusy');
182
- }
75
+ if (device.deviceId === 'default') {
76
+ return;
183
77
  }
184
78
 
185
- const devices = await navigator.mediaDevices.enumerateDevices();
186
-
187
- const videoDevices = [] as MediaDeviceInfo[];
188
- const audioDevices = [] as MediaDeviceInfo[];
189
- devices.forEach((device) => {
190
- if (device.deviceId === 'default') {
191
- return;
192
- }
79
+ if (device.kind === 'videoinput') {
80
+ videoDevices.push(device);
81
+ }
193
82
 
194
- if (device.kind === 'videoinput') {
195
- videoDevices.push(device);
196
- }
83
+ if (device.kind === 'audioinput') {
84
+ audioDevices.push(device);
85
+ }
86
+ });
197
87
 
198
- if (device.kind === 'audioinput') {
199
- audioDevices.push(device);
200
- }
201
- });
88
+ this.setAvailableVideoDevices(videoDevices);
89
+ this.setAvailableAudioDevices(audioDevices);
202
90
 
203
- this.setAvailableVideoDevices(videoDevices);
204
- this.setAvailableAudioDevices(audioDevices);
205
- this.isDevicesLoaded = true;
206
- this.logger.debug('detectDevices()', { videoDevices, audioDevices });
207
- } catch (error) {
208
- this.logger.error('detectDevices()', { error });
209
- throw new Error('Can`t detect devices');
210
- }
91
+ this.logger.debug('Devices list updated');
211
92
  }
212
93
 
213
- listenDevices(): void {
214
- navigator.mediaDevices.ondevicechange = () => {
215
- if (this.isDevicesLoaded) {
216
- this.logger.debug('Available devices list was changed');
217
- this.detectDevices();
218
- }
219
- };
220
- }
221
-
222
- stopVideoStream(): void {
223
- if (!this.videoStream) {
224
- this.logger.warn('stopVideoStream()', { message: 'No available video stream' });
94
+ async detectDevices(): Promise<void> {
95
+ if (this.isDevicesDetected) {
225
96
  return;
226
97
  }
227
98
 
228
- this.videoStream.getTracks().forEach((track) => {
229
- track.stop();
230
- });
231
-
232
- this.videoStream = undefined;
233
- this.logger.debug('stopVideoStream()');
234
- }
235
-
236
- stopAudioStream(): void {
237
- if (!this.audioStream) {
238
- this.logger.warn('stopVideoStream()', { message: 'No available audio stream' });
239
- return;
99
+ if (!this.isMediaDevicesAccessGranted) {
100
+ await this.requestMediaDevicesAccess();
240
101
  }
241
102
 
242
- this.audioStream.getTracks().forEach((track) => {
243
- track.stop();
103
+ navigator.mediaDevices.addEventListener('devicechange', () => {
104
+ this.refreshAvailableMediaDevicesList();
244
105
  });
245
106
 
246
- this.audioStream = undefined;
247
- this.logger.debug('stopAudioStream()');
248
- }
107
+ await this.refreshAvailableMediaDevicesList();
249
108
 
250
- async restartVideoStream(): Promise<void> {
251
- this.stopVideoStream();
252
- await this.startVideoStream();
109
+ this.isDevicesDetected = true;
253
110
  }
254
111
 
255
- async restartAudioStream(): Promise<void> {
256
- this.stopAudioStream();
257
- await this.startAudioStream();
112
+ listenDevices(): void {
113
+ navigator.mediaDevices.ondevicechange = async () => {
114
+ if (!this.isDevicesDetected) {
115
+ return;
116
+ }
117
+
118
+ await this.refreshAvailableMediaDevicesList();
119
+ this.clientEventEmitter.safeEmit(CLIENT_EVENTS.devicesListUpdated, {
120
+ audio: this.availableAudioDevices,
121
+ video: this.availableVideoDevices,
122
+ } as AvailableMediaDevices);
123
+ };
258
124
  }
259
125
  }
260
126
 
package/src/index.ts CHANGED
@@ -1,20 +1,39 @@
1
1
  import {
2
2
  AvailableMediaDevices,
3
+ CreateCameraVideoTrackOptions,
4
+ CreateMicrophoneAudioTrackOptions,
5
+ CreateScreenAudioTrackOptions,
6
+ CreateScreenVideoTrackOptions,
3
7
  JoinChannelParams,
4
- PublishAudioOptions,
5
- PublishVideoOptions,
8
+ Track,
6
9
  } from './types/common';
7
10
  import EnhancedEventEmitter from './EnhancedEventEmitter';
8
11
  import Engine from './engine';
9
12
  import Peer from './engine/Peer';
13
+ import { LoadBalancerApiClientParams } from './engine/network/LoadBalancerClient';
14
+
15
+ type ClientParams = {
16
+ network?: {
17
+ loadbalancer?: LoadBalancerApiClientParams,
18
+ },
19
+ };
10
20
 
11
21
  class Client {
12
22
  private readonly engine: Engine;
13
23
 
14
24
  private readonly _observer = new EnhancedEventEmitter();
15
25
 
16
- constructor() {
17
- this.engine = new Engine(this.observer);
26
+ constructor(params: ClientParams) {
27
+ const { network } = params;
28
+ this.engine = new Engine({
29
+ clientEventEmitter: this.observer,
30
+ network: {
31
+ loadbalancer: {
32
+ baseURL: network?.loadbalancer?.baseURL,
33
+ customNode: network?.loadbalancer?.customNode,
34
+ },
35
+ },
36
+ });
18
37
  }
19
38
 
20
39
  get observer(): EnhancedEventEmitter {
@@ -29,22 +48,6 @@ class Client {
29
48
  return this.engine.peers;
30
49
  }
31
50
 
32
- get isVideoEnabled(): boolean {
33
- return !!this.engine.media.videoProducer;
34
- }
35
-
36
- get isVideoPaused(): boolean {
37
- return !!this.engine.media.videoProducer?.paused;
38
- }
39
-
40
- get isAudioEnabled(): boolean {
41
- return !!this.engine.media.audioProducer;
42
- }
43
-
44
- get isAudioPaused(): boolean {
45
- return !!this.engine.media.audioProducer?.paused;
46
- }
47
-
48
51
  get availableVideoDevices(): MediaDeviceInfo[] {
49
52
  return this.engine.system.availableVideoDevices;
50
53
  }
@@ -53,14 +56,6 @@ class Client {
53
56
  return this.engine.system.availableAudioDevices;
54
57
  }
55
58
 
56
- get currentAudioDeviceId(): string | undefined {
57
- return this.engine.system.currentAudioDeviceId;
58
- }
59
-
60
- get currentVideoDeviceId(): string | undefined {
61
- return this.engine.system.currentVideoDeviceId;
62
- }
63
-
64
59
  async detectDevices(): Promise<AvailableMediaDevices> {
65
60
  await this.engine.system.detectDevices();
66
61
  return {
@@ -69,30 +64,6 @@ class Client {
69
64
  };
70
65
  }
71
66
 
72
- async getVideoStream(): Promise<MediaStream> {
73
- return this.engine.system.videoStream || this.engine.system.startVideoStream();
74
- }
75
-
76
- async getAudioStream(): Promise<MediaStream> {
77
- return this.engine.system.audioStream || this.engine.system.startAudioStream();
78
- }
79
-
80
- async getVideoTrack(): Promise<MediaStreamTrack> {
81
- return this.engine.system.getVideoTrack();
82
- }
83
-
84
- async getAudioTrack(): Promise<MediaStreamTrack> {
85
- return this.engine.system.getAudioTrack();
86
- }
87
-
88
- setVideoDevice(deviceId: string): void {
89
- this.engine.system.setCurrentVideoDevice(deviceId);
90
- }
91
-
92
- setAudioDevice(deviceId: string): void {
93
- this.engine.system.setCurrentAudioDevice(deviceId);
94
- }
95
-
96
67
  join(params: JoinChannelParams): Promise<void> {
97
68
  return this.engine.join(params);
98
69
  }
@@ -101,36 +72,36 @@ class Client {
101
72
  return this.engine.release();
102
73
  }
103
74
 
104
- publishVideo(track?: MediaStreamTrack, options?: PublishVideoOptions): Promise<void> {
105
- return this.engine.publishVideo(track, options);
75
+ publish(tracks: Track | Track[]): Promise<void> {
76
+ return this.engine.publish(tracks);
106
77
  }
107
78
 
108
- publishAudio(track?: MediaStreamTrack, options?: PublishAudioOptions): Promise<void> {
109
- return this.engine.publishAudio(track, options);
79
+ unpublish(tracks?: Track | Track[]): Promise<void> {
80
+ return this.engine.unpublish(tracks);
110
81
  }
111
82
 
112
- unpublishVideo(): Promise<void> {
113
- return this.engine.unpublishVideo();
83
+ pause(track: Track): Promise<void> {
84
+ return this.engine.pause(track);
114
85
  }
115
86
 
116
- unpublishAudio(): Promise<void> {
117
- return this.engine.unpublishAudio();
87
+ resume(track: Track): Promise<void> {
88
+ return this.engine.resume(track);
118
89
  }
119
90
 
120
- pauseVideo(): Promise<void> {
121
- return this.engine.pauseVideo();
91
+ createCameraVideoTrack(options?: CreateCameraVideoTrackOptions): Promise<Track | null> {
92
+ return this.engine.createCameraVideoTrack(options);
122
93
  }
123
94
 
124
- resumeVideo(): Promise<void> {
125
- return this.engine.resumeVideo();
95
+ createMicrophoneAudioTrack(options?: CreateMicrophoneAudioTrackOptions): Promise<Track | null> {
96
+ return this.engine.createMicrophoneAudioTrack(options);
126
97
  }
127
98
 
128
- pauseAudio(): Promise<void> {
129
- return this.engine.pauseAudio();
99
+ createScreenVideoTrack(options?: CreateScreenVideoTrackOptions): Promise<Track | null> {
100
+ return this.engine.createScreenVideoTrack(options);
130
101
  }
131
102
 
132
- resumeAudio(): Promise<void> {
133
- return this.engine.resumeAudio();
103
+ createScreenAudioTrack(options?: CreateScreenAudioTrackOptions): Promise<Track | null> {
104
+ return this.engine.createScreenAudioTrack(options);
134
105
  }
135
106
  }
136
107