@techsee/techsee-media-service 999.0.30 → 999.1.0-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/README.md +28 -27
- package/lib/LocalStreamManager.d.ts.map +1 -1
- package/lib/LocalStreamManager.js +8 -9
- package/lib/LocalStreamManager.js.map +1 -1
- package/lib/MediaConstants.d.ts +3 -19
- package/lib/MediaConstants.d.ts.map +1 -1
- package/lib/MediaConstants.js +7 -39
- package/lib/MediaConstants.js.map +1 -1
- package/lib/MediaContracts.d.ts +0 -4
- package/lib/MediaContracts.d.ts.map +1 -1
- package/lib/MediaContracts.js.map +1 -1
- package/lib/MediaPublisher.d.ts.map +1 -1
- package/lib/MediaPublisher.js.map +1 -1
- package/lib/MediaServiceBase.d.ts.map +1 -1
- package/lib/MediaServiceBase.js +0 -2
- package/lib/MediaServiceBase.js.map +1 -1
- package/lib/MediaSession/MediaServer.d.ts.map +1 -1
- package/lib/MediaSession/MediaServer.js.map +1 -1
- package/lib/MediaSession/MediaSessionBase.d.ts.map +1 -1
- package/lib/MediaSession/MediaSessionBase.js.map +1 -1
- package/lib/MediaSession/SessionOpentok.d.ts.map +1 -1
- package/lib/MediaSession/SessionOpentok.js.map +1 -1
- package/lib/MediaSession/SessionTurn.d.ts.map +1 -1
- package/lib/MediaSession/SessionTurn.js +5 -5
- package/lib/MediaSession/SessionTurn.js.map +1 -1
- package/lib/MediaSession/TurnConstants.js.map +1 -1
- package/lib/MediaSubscriber.d.ts.map +1 -1
- package/lib/MediaSubscriber.js +1 -8
- package/lib/MediaSubscriber.js.map +1 -1
- package/lib/MediaUtils/Compatibility.d.ts.map +1 -1
- package/lib/MediaUtils/Compatibility.js +1 -2
- package/lib/MediaUtils/Compatibility.js.map +1 -1
- package/lib/MediaUtils/MediaDomUtils.d.ts +2 -3
- package/lib/MediaUtils/MediaDomUtils.d.ts.map +1 -1
- package/lib/MediaUtils/MediaDomUtils.js +2 -21
- package/lib/MediaUtils/MediaDomUtils.js.map +1 -1
- package/lib/MediaUtils/MediaTracer.js.map +1 -1
- package/lib/MultiParty/Contracts.d.ts +15 -0
- package/lib/MultiParty/Contracts.d.ts.map +1 -0
- package/lib/MultiParty/{types.js → Contracts.js} +1 -1
- package/lib/MultiParty/Contracts.js.map +1 -0
- package/lib/MultiParty/DetectWebRtcService.d.ts +14 -16
- package/lib/MultiParty/DetectWebRtcService.d.ts.map +1 -1
- package/lib/MultiParty/DetectWebRtcService.js +44 -221
- package/lib/MultiParty/DetectWebRtcService.js.map +1 -1
- package/lib/MultiParty/MediaCapabilitiesHelper.d.ts +23 -0
- package/lib/MultiParty/MediaCapabilitiesHelper.d.ts.map +1 -0
- package/lib/MultiParty/MediaCapabilitiesHelper.js +408 -0
- package/lib/MultiParty/MediaCapabilitiesHelper.js.map +1 -0
- package/lib/MultiParty/{MultiPartyService.d.ts → MultiParty.d.ts} +36 -38
- package/lib/MultiParty/MultiParty.d.ts.map +1 -0
- package/lib/MultiParty/{MultiPartyService.js → MultiParty.js} +211 -11
- package/lib/MultiParty/MultiParty.js.map +1 -0
- package/lib/MultiParty/MultipartyFactory.d.ts +4 -0
- package/lib/MultiParty/MultipartyFactory.d.ts.map +1 -0
- package/lib/MultiParty/MultipartyFactory.js +21 -0
- package/lib/MultiParty/MultipartyFactory.js.map +1 -0
- package/lib/MultiParty/OpentokMultiparty.d.ts +34 -0
- package/lib/MultiParty/OpentokMultiparty.d.ts.map +1 -0
- package/lib/MultiParty/OpentokMultiparty.js +906 -0
- package/lib/MultiParty/OpentokMultiparty.js.map +1 -0
- package/lib/TechseeMediaStream.d.ts.map +1 -1
- package/lib/TechseeMediaStream.js.map +1 -1
- package/lib/oldCode/constants.js +25 -0
- package/lib/oldCode/constants.js.map +1 -0
- package/lib/oldCode/event-emitter.js +62 -0
- package/lib/oldCode/event-emitter.js.map +1 -0
- package/lib/oldCode/index.js +60 -0
- package/lib/oldCode/index.js.map +1 -0
- package/lib/oldCode/opentok/session.js +335 -0
- package/lib/oldCode/opentok/session.js.map +1 -0
- package/lib/oldCode/opentok/stream.js +324 -0
- package/lib/oldCode/opentok/stream.js.map +1 -0
- package/lib/oldCode/publisher.js +168 -0
- package/lib/oldCode/publisher.js.map +1 -0
- package/lib/oldCode/service.js +417 -0
- package/lib/oldCode/service.js.map +1 -0
- package/lib/oldCode/session.js +132 -0
- package/lib/oldCode/session.js.map +1 -0
- package/lib/oldCode/stream.js +223 -0
- package/lib/oldCode/stream.js.map +1 -0
- package/lib/oldCode/subscriber.js +115 -0
- package/lib/oldCode/subscriber.js.map +1 -0
- package/lib/oldCode/tracer.d.ts +36 -0
- package/lib/oldCode/tracer.d.ts.map +1 -0
- package/lib/oldCode/tracer.js +202 -0
- package/lib/oldCode/tracer.js.map +1 -0
- package/lib/oldCode/utils/ImageFixer.d.ts +1 -0
- package/lib/oldCode/utils/ImageFixer.d.ts.map +1 -0
- package/lib/oldCode/utils/ImageFixer.js +81 -0
- package/lib/oldCode/utils/ImageFixer.js.map +1 -0
- package/lib/oldCode/webrtc/constants.js +106 -0
- package/lib/oldCode/webrtc/constants.js.map +1 -0
- package/lib/oldCode/webrtc/helper.js +225 -0
- package/lib/oldCode/webrtc/helper.js.map +1 -0
- package/lib/oldCode/webrtc/session-kms.js +573 -0
- package/lib/oldCode/webrtc/session-kms.js.map +1 -0
- package/lib/oldCode/webrtc/session-loopback.js +354 -0
- package/lib/oldCode/webrtc/session-loopback.js.map +1 -0
- package/lib/oldCode/webrtc/session-turn.js +927 -0
- package/lib/oldCode/webrtc/session-turn.js.map +1 -0
- package/lib/oldCode/webrtc/session-turn.v2.js +592 -0
- package/lib/oldCode/webrtc/session-turn.v2.js.map +1 -0
- package/lib/oldCode/webrtc/session.js +58 -0
- package/lib/oldCode/webrtc/session.js.map +1 -0
- package/lib/oldCode/webrtc/stream.js +696 -0
- package/lib/oldCode/webrtc/stream.js.map +1 -0
- package/lib/oldCode/webrtc/temasys/adapter-loader.js +11 -0
- package/lib/oldCode/webrtc/temasys/adapter-loader.js.map +1 -0
- package/lib/oldCode/webrtc/temasys/adapter.js +5933 -0
- package/lib/oldCode/webrtc/temasys/adapter.js.map +1 -0
- package/lib/oldCode/webrtc/webrtc-ie-shim.js +3437 -0
- package/lib/oldCode/webrtc/webrtc-ie-shim.js.map +1 -0
- package/lib/qos/raw-qos.js +2 -2
- package/lib/qos/raw-qos.js.map +1 -1
- package/lib/webrtc-ie-shim.js +1 -1
- package/lib/webrtc-ie-shim.js.map +1 -1
- package/package.json +25 -41
- package/lib/MediaUtils/index.d.ts +0 -1
- package/lib/MediaUtils/index.d.ts.map +0 -1
- package/lib/MediaUtils/index.js +0 -16
- package/lib/MediaUtils/index.js.map +0 -1
- package/lib/MultiParty/MediaCapabilitiesService.d.ts +0 -17
- package/lib/MultiParty/MediaCapabilitiesService.d.ts.map +0 -1
- package/lib/MultiParty/MediaCapabilitiesService.js +0 -327
- package/lib/MultiParty/MediaCapabilitiesService.js.map +0 -1
- package/lib/MultiParty/MediaCapabilitiesUtils.d.ts +0 -5
- package/lib/MultiParty/MediaCapabilitiesUtils.d.ts.map +0 -1
- package/lib/MultiParty/MediaCapabilitiesUtils.js +0 -305
- package/lib/MultiParty/MediaCapabilitiesUtils.js.map +0 -1
- package/lib/MultiParty/MediaTracer.d.ts +0 -3
- package/lib/MultiParty/MediaTracer.d.ts.map +0 -1
- package/lib/MultiParty/MediaTracer.js +0 -17
- package/lib/MultiParty/MediaTracer.js.map +0 -1
- package/lib/MultiParty/MultiPartyService.d.ts.map +0 -1
- package/lib/MultiParty/MultiPartyService.js.map +0 -1
- package/lib/MultiParty/MultiPartyServiceFactory.d.ts +0 -3
- package/lib/MultiParty/MultiPartyServiceFactory.d.ts.map +0 -1
- package/lib/MultiParty/MultiPartyServiceFactory.js +0 -21
- package/lib/MultiParty/MultiPartyServiceFactory.js.map +0 -1
- package/lib/MultiParty/MultipartyServiceEventTypes.d.ts +0 -84
- package/lib/MultiParty/MultipartyServiceEventTypes.d.ts.map +0 -1
- package/lib/MultiParty/MultipartyServiceEventTypes.js +0 -20
- package/lib/MultiParty/MultipartyServiceEventTypes.js.map +0 -1
- package/lib/MultiParty/index.d.ts +0 -6
- package/lib/MultiParty/index.d.ts.map +0 -1
- package/lib/MultiParty/index.js +0 -45
- package/lib/MultiParty/index.js.map +0 -1
- package/lib/MultiParty/opentok/OpentokMultiPartyService.d.ts +0 -35
- package/lib/MultiParty/opentok/OpentokMultiPartyService.d.ts.map +0 -1
- package/lib/MultiParty/opentok/OpentokMultiPartyService.js +0 -787
- package/lib/MultiParty/opentok/OpentokMultiPartyService.js.map +0 -1
- package/lib/MultiParty/opentok/OpentokPublisher.d.ts +0 -29
- package/lib/MultiParty/opentok/OpentokPublisher.d.ts.map +0 -1
- package/lib/MultiParty/opentok/OpentokPublisher.js +0 -273
- package/lib/MultiParty/opentok/OpentokPublisher.js.map +0 -1
- package/lib/MultiParty/opentok/OpentokPublisherEventMapper.d.ts +0 -19
- package/lib/MultiParty/opentok/OpentokPublisherEventMapper.d.ts.map +0 -1
- package/lib/MultiParty/opentok/OpentokPublisherEventMapper.js +0 -69
- package/lib/MultiParty/opentok/OpentokPublisherEventMapper.js.map +0 -1
- package/lib/MultiParty/opentok/OpentokScreenPublisher.d.ts +0 -5
- package/lib/MultiParty/opentok/OpentokScreenPublisher.d.ts.map +0 -1
- package/lib/MultiParty/opentok/OpentokScreenPublisher.js +0 -85
- package/lib/MultiParty/opentok/OpentokScreenPublisher.js.map +0 -1
- package/lib/MultiParty/opentok/OpentokSubscriber.d.ts +0 -1
- package/lib/MultiParty/opentok/OpentokSubscriber.d.ts.map +0 -1
- package/lib/MultiParty/opentok/OpentokSubscriber.js +0 -34
- package/lib/MultiParty/opentok/OpentokSubscriber.js.map +0 -1
- package/lib/MultiParty/opentok/OpentokVideoPublisher.d.ts +0 -14
- package/lib/MultiParty/opentok/OpentokVideoPublisher.d.ts.map +0 -1
- package/lib/MultiParty/opentok/OpentokVideoPublisher.js +0 -325
- package/lib/MultiParty/opentok/OpentokVideoPublisher.js.map +0 -1
- package/lib/MultiParty/opentok/trace.d.ts +0 -2
- package/lib/MultiParty/opentok/trace.d.ts.map +0 -1
- package/lib/MultiParty/opentok/trace.js +0 -31
- package/lib/MultiParty/opentok/trace.js.map +0 -1
- package/lib/MultiParty/opentok.d.ts +0 -453
- package/lib/MultiParty/types.d.ts +0 -28
- package/lib/MultiParty/types.d.ts.map +0 -1
- package/lib/MultiParty/types.js.map +0 -1
- package/lib/MultiParty/utils.d.ts +0 -9
- package/lib/MultiParty/utils.d.ts.map +0 -1
- package/lib/MultiParty/utils.js +0 -27
- package/lib/MultiParty/utils.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
# @techsee/techsee-media-service
|
|
2
2
|
|
|
3
3
|
**General Info**
|
|
4
|
-
This package is a starting point for creating Techsee Media SDK.
|
|
4
|
+
This package is a starting point for creating Techsee Media SDK.
|
|
5
5
|
It contains basic framework for creating applications that utilizes media abilities.
|
|
6
6
|
It can be video and/or audio, with or without streaming over WebRTC protocol.
|
|
7
|
-
The framework currently supports: Video+Voip over Techsee Video (Turn) + IE Plugin and OpenTOK + IE Plugin.
|
|
7
|
+
The framework currently supports: Video+Voip over Techsee Video (Turn) + IE Plugin and OpenTOK + IE Plugin.
|
|
8
8
|
|
|
9
9
|
You can see a very simple demo, which demonstrates how to create very basic MediaService implementation and use it for rendering video in react component.
|
|
10
|
-
Clone the repository, run `npm i`, then run `npm run demo`. The source code of the demo, can be found in ./demo folder.
|
|
10
|
+
Clone the repository, run `npm i`, then run `npm run demo`. The source code of the demo, can be found in ./demo folder.
|
|
11
11
|
|
|
12
12
|
---
|
|
13
13
|
|
|
14
14
|
Some basic framework principles are described below, which will help you to work with media framework.
|
|
15
15
|
|
|
16
16
|
**Framework actors**
|
|
17
|
-
`MediaStreamTrack` -
|
|
18
|
-
It can be video track (WebCam or ScreenShare), or audio track (Microphone stream).
|
|
19
|
-
|
|
17
|
+
`MediaStreamTrack` - WebRTC object, the most basic media unit.
|
|
18
|
+
It can be video track (WebCam or ScreenShare), or audio track (Microphone stream).
|
|
19
|
+
|
|
20
20
|
`MediaStream` - WebRTC object that just organizes multiple `MediaStreamTracks` into single group.
|
|
21
21
|
The same `MediaStreamTrack` can belong to multiple `MediaStreams`.
|
|
22
|
-
In Techsee Media Service implementation, `MediaStream` can not contain more than one `MediaStreamTrack` and it used only because HTML5 video element works with `MediaStream` object.
|
|
22
|
+
In Techsee Media Service implementation, `MediaStream` can not contain more than one `MediaStreamTrack` and it used only because HTML5 video element works with `MediaStream` object.
|
|
23
23
|
|
|
24
24
|
`TechseeMediaStream` - This is a logical wrapper for WebRTC `MediaStreamTrack` and manages some additional information regarding the specific `MediaStreamTrack`.
|
|
25
25
|
For example this object has the type of the `MediaStreamTrack` (USER_VIDEO, AGENT_AUDIO...etc), has indication if track is local or remote.
|
|
@@ -27,57 +27,58 @@ For example this object has the type of the `MediaStreamTrack` (USER_VIDEO, AGEN
|
|
|
27
27
|
`MediaSubscriber` - Techsee logical unit, that responsible to render `MediaStreams` into DOM.
|
|
28
28
|
In simple words this object creates video element in html, and renders `MediaStream` into it, when stream is ready.
|
|
29
29
|
`MediaSubscriber` is created for specific `MediaStream`, and whenever that stream created, the subscriber will start playing it.
|
|
30
|
-
The subscriber will notify it's consumers about the state changes through `onStateChanged` method.
|
|
30
|
+
The subscriber will notify it's consumers about the state changes through `onStateChanged` method.
|
|
31
31
|
|
|
32
32
|
`MediaSession` - Techsee logical unit, that used to stream video over WebRTC protocol. This object is responsible to handle all aspect of peers connectivity, including signaling, or third party service handling, like OpenTok.
|
|
33
33
|
When connection with peer established, this service registers `MediaStreamTracks` that received from peer and publishes local streams the connected peer.
|
|
34
34
|
Current implementation contains `MediaSessionBase` object, which have basic abstractions for all types of sessions. `SessionTurn` which handles the Techsee video sessions over TURN server.
|
|
35
35
|
`SessionOpentok` which handles the session connectivity over OpenTok third party service.
|
|
36
|
-
|
|
36
|
+
|
|
37
37
|
`RTCPeerConnection` - WebRTC object that represents connection with single peer, when SessionTurn is used for session. The same peer is used to send and/or receive media information.
|
|
38
38
|
|
|
39
|
-
`OTPeerConnection` - Design time only Typescript abstraction, which represents the connectivity with peer over OpenTok session.
|
|
39
|
+
`OTPeerConnection` - Design time only Typescript abstraction, which represents the connectivity with peer over OpenTok session.
|
|
40
40
|
|
|
41
41
|
`MediaPublisher` - Techsee logical unit which organizes local MediaStreamTracks into single MediaStream for publishing.
|
|
42
42
|
|
|
43
43
|
`MediaService` - Techsee logical unit. Represents the Facade of the framework and glues all of the above together.
|
|
44
44
|
Current implementation provides `MediaServiceBase` abstract object that contains all base logic and tools for displaying media locally or streaming it over WebRTC.
|
|
45
|
-
Each application should create its concrete `MediaService` and fill specific application logic gaps.
|
|
45
|
+
Each application should create its concrete `MediaService` and fill specific application logic gaps.
|
|
46
46
|
For example, currently exist `DashboardMediaService` in `techsee-app` and `MobileMediaService` in `techee-mobile`.
|
|
47
47
|
|
|
48
48
|
---
|
|
49
49
|
|
|
50
50
|
**Consuming media service - High Level Flow**
|
|
51
|
-
|
|
51
|
+
|
|
52
52
|
In order to be able to use media service, first you need to create and instance of it and initialize it.
|
|
53
|
-
Depending on application, the constructor parameters can be different, but MediaServiceBase need to get the following in it's constructor:
|
|
53
|
+
Depending on application, the constructor parameters can be different, but MediaServiceBase need to get the following in it's constructor:
|
|
54
54
|
|
|
55
55
|
`let mediaService = new SomeSpecificMediaService(environment, webRtcInfo);`
|
|
56
|
+
|
|
57
|
+
* **environment: IMediaEnvironment** - Service which will help understand in which environment the media service is currently running.
|
|
58
|
+
* **webRtcSupportInfo: ClientWebRtcInfo** - Information about WebRTC support on currently running device
|
|
56
59
|
|
|
57
|
-
- **environment: IMediaEnvironment** - Service which will help understand in which environment the media service is currently running.
|
|
58
|
-
- **webRtcSupportInfo: ClientWebRtcInfo** - Information about WebRTC support on currently running device
|
|
59
60
|
|
|
60
61
|
When instance of specific MediaService was created, it should be initialized with `mediaService.initMediaService(serviceOptions)` method.
|
|
61
62
|
See `MediaServiceOptions` for options details. The method returns promise that resolved when initialization is done.
|
|
62
63
|
Initialization process, detects what media support currently running device have.
|
|
63
64
|
It checks if video can be played (natively or using IE plugins), if device have mic and so on...
|
|
64
|
-
After initialization promise resolved, the device information get be accessed through `mediaService.deviceSupportInfo`.
|
|
65
|
+
After initialization promise resolved, the device information get be accessed through `mediaService.deviceSupportInfo`.
|
|
65
66
|
|
|
66
|
-
|
|
67
|
+
***Note:*** Before promise returned by `mediaService.initMediaService(serviceOptions)` was not resolved, you not able to call `mediaService.initLocalMediaStreams(serviceOptions)`,
|
|
67
68
|
but you can create media subscribers if needed by calling `mediaService.createSubscriber(subscriberParams)`.
|
|
68
69
|
|
|
69
70
|
If audio stream is needed during the session, `mediaService.enableVoipDuringSession()` method should be called before initializing local streams.
|
|
70
|
-
After initialization was done and promise was resolved `mediaService.initLocalMediaStreams(serviceOptions)` can be called when video/audio streams should be created.
|
|
71
|
+
After initialization was done and promise was resolved `mediaService.initLocalMediaStreams(serviceOptions)` can be called when video/audio streams should be created.
|
|
71
72
|
This method will start the local MediaStream creation process, and Camera/ScreenShare approval dialog will popup if there permission currently exists.
|
|
72
73
|
`initLocalMediaStreams` method is called by controller which displays local media stream on mobile, and in MediaSession, when `peerConnection ` is created.
|
|
73
|
-
`initLocalMediaStreams` synchronizes the calls and insures there only one instance of stream exists, and both sides receives the same one.
|
|
74
|
-
|
|
75
|
-
As mentioned before, `mediaService.createSubscriber(subscriberParams)` can be called even before initialization, so whenever you have the `div` container that should hold video element,
|
|
76
|
-
you can create the subscriber, by providing `KnownMediaStream` and `div` as container. Whenever the stream is ready, it will be played automatically by `MediaSubscriber`.
|
|
77
|
-
`MediaSubscriber` will create `video` element, add it to `div` container and will insure it plays.
|
|
78
|
-
`MediaSubscriber` has 'onStateChanged' method, which can be used for being notified on state changes of the subscriber.
|
|
79
|
-
It will notify when it starts or stops playing the video, or when it has been muted or unmuted. In event listener you can inspect properties of the subscriber to see in which state it currently exists.
|
|
80
|
-
In addition, `MediaSubscriber` has `onDispose` event handler, which will be called after `MediaSubscriber` was disposed and will never play video again, so references to it can be removed in order to avoid memory leaks.
|
|
74
|
+
`initLocalMediaStreams` synchronizes the calls and insures there only one instance of stream exists, and both sides receives the same one.
|
|
75
|
+
|
|
76
|
+
As mentioned before, `mediaService.createSubscriber(subscriberParams)` can be called even before initialization, so whenever you have the `div` container that should hold video element,
|
|
77
|
+
you can create the subscriber, by providing `KnownMediaStream` and `div` as container. Whenever the stream is ready, it will be played automatically by `MediaSubscriber`.
|
|
78
|
+
`MediaSubscriber` will create `video` element, add it to `div` container and will insure it plays.
|
|
79
|
+
`MediaSubscriber` has 'onStateChanged' method, which can be used for being notified on state changes of the subscriber.
|
|
80
|
+
It will notify when it starts or stops playing the video, or when it has been muted or unmuted. In event listener you can inspect properties of the subscriber to see in which state it currently exists.
|
|
81
|
+
In addition, `MediaSubscriber` has `onDispose` event handler, which will be called after `MediaSubscriber` was disposed and will never play video again, so references to it can be removed in order to avoid memory leaks.
|
|
81
82
|
|
|
82
83
|
**Connecting to WebRTC Media Session - High Level Flow**
|
|
83
84
|
|
|
@@ -85,4 +86,4 @@ After initialization promise was resolved, `mediaService.connectToSession(sessio
|
|
|
85
86
|
Connection to session can be done before media streams were initialized, if your use case requires it.
|
|
86
87
|
In case of of Techsee Live implementation, connection to session is done only when Terms and camera access approved by the user.
|
|
87
88
|
Depending on configuration passed in initialization method, `SessionTurn` or `SessionOpentok` will be created to manage the media session peers.
|
|
88
|
-
Whenever WebRTC peer will be connected, MediaSession instance will ask from `mediaService` for MediaStream that should be published to connected peer.
|
|
89
|
+
Whenever WebRTC peer will be connected, MediaSession instance will ask from `mediaService` for MediaStream that should be published to connected peer.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/LocalStreamManager.ts"],"names":[],"mappings":"AASA,OAAO,EAAC,QAAQ,EAAC,MAAM,yBAAyB,CAAC;AAEjD,OAAO,EACH,iBAAiB,EACjB,qBAAqB,EACrB,2BAA2B,EAE3B,yBAAyB,EAE5B,MAAM,kBAAkB,CAAC;AAY1B,OAAO,CAAC,MAAM,CAAC;IACX,UAAU,MAAM;QACZ,qBAAqB,EAAE,QAAQ,CAAC,yBAAyB,CAAC,CAAC;QAC3D,wBAAwB,EAAE,QAAQ,CAAC,yBAAyB,CAAC,CAAC;QAC9D,2BAA2B,EAAE,QAAQ,CAAC,qBAAqB,CAAC,CAAC;QAC7D,0BAA0B,EAAE,OAAO,CAAC;KACvC;CACJ;AAeD,UAAU,eAAe;IACrB,KAAK,EAAE,QAAQ,CAAC;QAAC,IAAI,CAAC,EAAE,eAAe,CAAC;QAAC,KAAK,CAAC,EAAE,eAAe,CAAA;KAAC,CAAC,CAAC;IACnE,KAAK,EAAE,QAAQ,CAAC,eAAe,CAAC,CAAC;IACjC,YAAY,EAAE,MAAM,CAAC;CACxB;AAED,qBAAa,kBAAkB;IAC3B,OAAO,CAAC,WAAW,CAAoB;IAEvC,OAAO,CAAC,eAAe,CAAgE;gBAE3E,WAAW,EAAE,iBAAiB;IAO1C,IAAI,cAAc,oBAEjB;IAED,kBAAkB,CAAC,WAAW,EAAE,qBAAqB,GAAG,OAAO,CAAC,yBAAyB,CAAC;IA4C1F,qBAAqB,CAAC,WAAW,EAAE,2BAA2B,GAAG,OAAO,CAAC,yBAAyB,CAAC;IA4CnG,sBAAsB,IAAI,OAAO,CAAC,IAAI,CAAC;IAuBvC,yBAAyB,IAAI,OAAO,CAAC,IAAI,CAAC;IAqB1C,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC;IAMhC,OAAO,CAAC,0BAA0B;IAkElC,OAAO,CAAC,6BAA6B;IAoBrC,OAAO,CAAC,mCAAmC;IA0E3C,iBAAiB,CAAC,cAAc,EAAE;QAAC,KAAK,EAAE,eAAe,EAAE,CAAC;QAAC,KAAK,EAAE,eAAe,EAAE,CAAA;KAAC;IAWtF,OAAO,CAAC,oBAAoB;IA6E5B,OAAO,CAAC,wBAAwB;CA+BnC","file":"LocalStreamManager.d.ts","sourcesContent":["// eslint-disable-next-line eslint-comments/disable-enable-pair\n/*eslint-disable operator-linebreak */\nimport assign from 'lodash/assign';\nimport get from 'lodash/get';\nimport last from 'lodash/last';\nimport first from 'lodash/first';\nimport cloneDeep from 'lodash/cloneDeep';\nimport {Promise} from 'bluebird';\n\nimport {Nullable} from '@techsee/techsee-common';\n\nimport {\n IMediaEnvironment,\n LocalMediaConstraints,\n LocalVideoStreamConstraints,\n MediaRequestFailResult,\n MediaRequestSuccessResult,\n VideoStreamResolution\n} from './MediaContracts';\n\nimport {\n CameraTypes,\n ConstraintType,\n DEFAULT_VIDEO_CONSTRAINT_TYPE,\n DEFAULT_VIDEO_RESOLUTION,\n LocalVideoSourceType,\n MediaRequestErrorCode\n} from './MediaConstants';\nimport {getMediaTracer} from './MediaUtils/MediaTracer';\n\ndeclare global {\n interface Window {\n latestUserMediaStream: Nullable<MediaRequestSuccessResult>;\n latestDesktopMediaStream: Nullable<MediaRequestSuccessResult>;\n latestLocalMediaConstraints: Nullable<LocalMediaConstraints>;\n mediaStreamAlreadyReplaced: boolean;\n }\n}\n\ndeclare const window: Window;\n\nwindow.latestUserMediaStream = null;\nlet userMediaPromise: Nullable<Promise<MediaRequestSuccessResult>> = null;\n\nwindow.latestDesktopMediaStream = null;\nlet desktopMediaPromise: Nullable<Promise<MediaRequestSuccessResult>> = null;\n\nwindow.mediaStreamAlreadyReplaced = false;\nwindow.latestLocalMediaConstraints = null;\n\nconst trace = getMediaTracer('LocalStreamManager');\n\ninterface IGroupedDevices {\n video: Nullable<{back?: MediaDeviceInfo; front?: MediaDeviceInfo}>;\n audio: Nullable<MediaDeviceInfo>;\n camerasCount: number;\n}\n\nexport class LocalStreamManager {\n private environment: IMediaEnvironment;\n\n private _groupedDevices: IGroupedDevices = {video: null, audio: null, camerasCount: 0};\n\n constructor(environment: IMediaEnvironment) {\n this.environment = environment;\n\n this.parseMediaErrorThenThrow = this.parseMediaErrorThenThrow.bind(this);\n this.clearAllStreams = this.clearAllStreams.bind(this);\n }\n\n get groupedDevices() {\n return this._groupedDevices;\n }\n\n getUserMediaStream(constraints: LocalMediaConstraints): Promise<MediaRequestSuccessResult> {\n trace.info('getUserMediaStream', constraints);\n if (userMediaPromise) {\n return userMediaPromise;\n }\n\n if (window.latestUserMediaStream) {\n const videoTrack = window.latestUserMediaStream.mediaStream.getVideoTracks();\n\n if (videoTrack.length > 0 && videoTrack[0].readyState === 'live') {\n return Promise.resolve({...window.latestUserMediaStream, isNew: false});\n }\n\n this.destroyUserMediaStream();\n }\n\n userMediaPromise = new Promise((resolve, reject) => {\n const catchHandler = (err: any): void => {\n userMediaPromise = null;\n window.latestUserMediaStream = null;\n trace.error('getUserMedia error', err);\n reject(err);\n };\n\n try {\n this.getHighestResolutionStream(false, constraints)\n .then((streamResult: MediaRequestSuccessResult) => {\n userMediaPromise = null;\n window.latestUserMediaStream = streamResult;\n window.latestLocalMediaConstraints = cloneDeep(constraints);\n window.latestLocalMediaConstraints.audio = (streamResult.constraint &&\n streamResult.constraint.audio) as boolean;\n\n resolve({...window.latestUserMediaStream, isNew: true});\n })\n .catch(catchHandler);\n } catch (err) {\n catchHandler(err);\n }\n });\n\n return userMediaPromise;\n }\n\n getDesktopMediaStream(constraints: LocalVideoStreamConstraints): Promise<MediaRequestSuccessResult> {\n if (desktopMediaPromise) {\n return desktopMediaPromise;\n }\n\n trace.info('getDesktopMediaStream', constraints);\n\n if (window.latestDesktopMediaStream) {\n const track = window.latestDesktopMediaStream.mediaStream.getVideoTracks();\n\n if (track.length > 0 && track[0].readyState === 'live') {\n //return Promise.resolve();\n return Promise.resolve({...window.latestDesktopMediaStream, isNew: false});\n }\n this.destroyDesktopMediaStream().catch((error: any) => {\n trace.error('Error destroying desktop media stream', error);\n });\n }\n\n desktopMediaPromise = new Promise((resolve, reject) => {\n const mediaCatchHandler = (err: any): void => {\n desktopMediaPromise = null;\n window.latestDesktopMediaStream = null;\n trace.error('getDisplayMedia error', err);\n reject(err);\n };\n\n try {\n this.getHighestResolutionStream(true, {video: constraints, audio: false})\n .then((streamResult: MediaRequestSuccessResult) => {\n desktopMediaPromise = null;\n window.latestDesktopMediaStream = streamResult;\n\n resolve({...window.latestDesktopMediaStream, isNew: true});\n })\n .catch(mediaCatchHandler);\n } catch (err) {\n mediaCatchHandler(err);\n }\n });\n\n return desktopMediaPromise;\n }\n\n destroyUserMediaStream(): Promise<void> {\n const streamResult = window.latestUserMediaStream;\n\n userMediaPromise = null;\n window.latestUserMediaStream = null;\n window.latestLocalMediaConstraints = null;\n window.mediaStreamAlreadyReplaced = false;\n\n if (streamResult && streamResult.mediaStream) {\n try {\n streamResult.mediaStream.getTracks().forEach((track: MediaStreamTrack) => {\n track.stop();\n });\n\n trace.info('destroyUserMediaStream - stop all tracks');\n } catch (e) {\n trace.info('destroyUserMediaStream - Failed to stop all tracks', e);\n }\n }\n\n return Promise.resolve();\n }\n\n destroyDesktopMediaStream(): Promise<void> {\n const streamResult = window.latestDesktopMediaStream;\n\n window.latestDesktopMediaStream = null;\n desktopMediaPromise = null;\n\n if (streamResult && streamResult.mediaStream) {\n try {\n streamResult.mediaStream.getTracks().forEach((track: MediaStreamTrack) => {\n track.stop();\n });\n\n trace.info('destroyDesktopMediaStream - stop all tracks');\n } catch (e) {\n trace.info('destroyDesktopMediaStream - Failed to stop all tracks', e);\n }\n }\n\n return Promise.resolve();\n }\n\n clearAllStreams(): Promise<void> {\n trace.info('LocalStreamManager Clearing all streams');\n\n return Promise.all([this.destroyDesktopMediaStream(), this.destroyUserMediaStream()]).then(() => undefined);\n }\n\n private getHighestResolutionStream(\n isDesktopMedia: boolean,\n constraints?: LocalMediaConstraints\n ): Promise<MediaRequestSuccessResult> {\n const constraintsCandidates = this.getParsedConstraints(isDesktopMedia, constraints);\n\n trace.info('getHighestResolutionStream - constraintsCandidates:', constraintsCandidates);\n\n if (constraintsCandidates.length === 0) {\n return Promise.reject(new Error('No constraints to retrieve the stream'));\n }\n\n return new Promise((resolve, reject) => {\n let lastSuccessfulResult: Nullable<MediaRequestSuccessResult> = null;\n let lastFailedResult: Nullable<MediaRequestFailResult> = null;\n let isStreamRequestFulfilled = false;\n\n (Promise as any)\n .reduce(\n constraintsCandidates,\n (total: any, candidate: MediaStreamConstraints) => {\n if (isStreamRequestFulfilled) {\n return;\n }\n\n const constraintType =\n get(constraints, 'video.videoResolution.constraintType') ||\n get(constraints, 'video.videoResolution[0].constraintType');\n\n return this.getStreamPromiseByParsedConstraints(candidate, isDesktopMedia)\n .then((stream: MediaStream) => {\n lastSuccessfulResult = {\n mediaStream: stream,\n constraint: candidate,\n constraintType,\n isNew: true\n };\n trace.info('getHighestResolutionStream Success', lastSuccessfulResult);\n isStreamRequestFulfilled = true;\n resolve(lastSuccessfulResult);\n })\n .catch((failResult: MediaRequestFailResult) => {\n lastFailedResult = failResult;\n\n if (lastFailedResult.errorCode === MediaRequestErrorCode.PermissionDenied) {\n isStreamRequestFulfilled = true;\n reject(lastFailedResult);\n }\n });\n },\n 0\n )\n .then(() => {\n if (!isStreamRequestFulfilled) {\n if (!lastFailedResult) {\n lastFailedResult = {\n errorCode: MediaRequestErrorCode.GeneralError,\n message: 'Suitable stream cannot be created'\n };\n }\n reject(lastFailedResult);\n }\n });\n });\n }\n\n private getUserMediaStreamMediaDevice(constraints: MediaStreamConstraints, isDesktopMedia: boolean) {\n let streamPromise = null;\n\n if (!isDesktopMedia) {\n streamPromise = navigator.mediaDevices.getUserMedia(constraints);\n } else {\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n //@ts-ignore\n streamPromise = navigator.mediaDevices.getDisplayMedia\n ? // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n //@ts-ignore\n navigator.mediaDevices.getDisplayMedia(constraints)\n : // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n //@ts-ignore\n navigator.getDisplayMedia(constraints);\n }\n\n return streamPromise;\n }\n\n private getStreamPromiseByParsedConstraints(\n constraints: MediaStreamConstraints,\n isDesktopMedia: boolean\n ): Promise<MediaStream> {\n trace.info('getStreamPromiseByParsedConstraints', constraints);\n\n try {\n return this.getUserMediaStreamMediaDevice(constraints, isDesktopMedia).catch((err: any) => {\n let streamPromise = null;\n\n trace.info('getStreamPromiseByParsedConstraints - get user stream error', err.name);\n\n // Android (Galaxy esp.) have a bug that when using facingMode it might cause NotReadableError. So\n // we should try again but without facingMode. The exception to the rule is when we don't have specific\n // device to use (like in IOS13 bug, as can be seen in MediaServiceBase.ts), in that case, we might end\n // up using the front camera, which is a privacy concern and the preference is to fallback from video\n if (\n err &&\n err.name === 'NotReadableError' &&\n get(constraints, 'video.facingMode') &&\n get(constraints, 'video.deviceId')\n ) {\n const newConstraints = constraints;\n\n trace.info(\n `getStreamPromiseByParsedConstraints - NotReadableError - Failed to get video user media stream with facingMode=${get(\n constraints,\n 'video.facingMode'\n )}`,\n err.name\n );\n\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n delete newConstraints.video.facingMode;\n ((newConstraints.video as MediaTrackConstraints).deviceId as ConstrainDOMStringParameters) = {\n exact: (constraints.video as MediaTrackConstraints).deviceId\n } as any as ConstrainDOMStringParameters;\n\n streamPromise = this.getStreamPromiseByParsedConstraints(newConstraints, isDesktopMedia);\n } else if (err && err.name && constraints.audio && !constraints.video) {\n trace.info(\n 'getStreamPromiseByParsedConstraints - audioStreamFailed - Failed to get audio user media stream',\n err.name\n );\n\n return this.parseMediaErrorThenThrow({name: 'audioStreamFailed'});\n } else if (err && err.name && constraints.audio) {\n const newConstraints = constraints;\n\n trace.info(\n 'getStreamPromiseByParsedConstraints - Failed to get video and audio user media stream, try to get video media stream only',\n err.name\n );\n\n newConstraints.audio = false;\n streamPromise = this.getStreamPromiseByParsedConstraints(newConstraints, isDesktopMedia);\n } else if (err && !streamPromise) {\n trace.info(\n 'getStreamPromiseByParsedConstraints - Failed to get video user media stream',\n err && err.name\n );\n\n streamPromise = Promise.reject(err);\n }\n\n return streamPromise && streamPromise.catch(this.parseMediaErrorThenThrow);\n });\n } catch (e) {\n // @ts-ignore\n return this.parseMediaErrorThenThrow(e);\n }\n }\n\n setGroupedDevices(groupedDevices: {video: MediaDeviceInfo[]; audio: MediaDeviceInfo[]}) {\n trace.info('setGroupedDevices', groupedDevices);\n this._groupedDevices = {\n video: groupedDevices.video\n ? {[CameraTypes.BACK]: last(groupedDevices.video), [CameraTypes.FRONT]: first(groupedDevices.video)}\n : null,\n audio: last(groupedDevices.audio) || null,\n camerasCount: groupedDevices.video.length\n };\n }\n\n private getParsedConstraints(\n isDesktopMedia: boolean,\n streamConstraints?: LocalMediaConstraints\n ): MediaStreamConstraints[] {\n const constraintCandidates: MediaStreamConstraints[] = [];\n\n //TODO - Alex: need to understand which constraints not compatible with screen share\n if (isDesktopMedia) {\n return [{video: true}];\n }\n\n if (!streamConstraints) {\n return constraintCandidates;\n }\n\n const baseConstraints: MediaStreamConstraints = {};\n\n baseConstraints.audio = typeof streamConstraints.audio === 'boolean' ? streamConstraints.audio : undefined;\n\n if (!streamConstraints.video) {\n return [baseConstraints];\n }\n\n const cameraType =\n streamConstraints.video !== 'boolean' &&\n (streamConstraints.video as LocalVideoStreamConstraints).videoSourceType;\n\n baseConstraints.video = {\n facingMode: cameraType && cameraType === LocalVideoSourceType.CAMERA_FRONT ? 'user' : 'environment',\n frameRate: {ideal: 15, max: 30}\n };\n\n const deviceId = get(\n this._groupedDevices,\n `video.${cameraType === LocalVideoSourceType.CAMERA_FRONT ? CameraTypes.FRONT : CameraTypes.BACK}.deviceId`\n );\n\n if (deviceId) {\n baseConstraints.video.deviceId = deviceId;\n\n if (this._groupedDevices.camerasCount > 1) {\n baseConstraints.video.facingMode = {\n exact: baseConstraints.video.facingMode\n } as any as ConstrainDOMStringParameters;\n }\n }\n\n const assignConstraint = (videoResolution: VideoStreamResolution): void => {\n const [width, height] = videoResolution.resolution.split('x');\n const constraintCandidate = assign({}, baseConstraints);\n\n constraintCandidate.video = assign({}, baseConstraints.video, {\n width: _constraintByType(width, videoResolution.constraintType),\n height: _constraintByType(height, videoResolution.constraintType)\n });\n constraintCandidates.push(constraintCandidate);\n };\n\n if (\n (baseConstraints.video && typeof streamConstraints.video === 'boolean') ||\n !((streamConstraints.video as LocalVideoStreamConstraints).videoResolution instanceof Array)\n ) {\n const defaultResolution: VideoStreamResolution = {\n resolution: DEFAULT_VIDEO_RESOLUTION,\n constraintType: DEFAULT_VIDEO_CONSTRAINT_TYPE\n };\n\n assignConstraint(defaultResolution);\n\n return constraintCandidates;\n }\n\n (streamConstraints.video as any).videoResolution.forEach(assignConstraint);\n\n return constraintCandidates;\n }\n\n private parseMediaErrorThenThrow(error: any): MediaRequestFailResult {\n if (error && error.errorCode) {\n throw error;\n }\n\n trace.error('Get media stream error.', error);\n const errorName = error && error.name ? error.name : '';\n\n const permissionErrorNames = ['NotAllowedError', 'PermissionDismissedError', 'PermissionDeniedError'];\n\n // const generalError = [\n // 'NotFoundError',\n // 'DevicesNotFoundError',\n // 'NotReadableError',\n // 'TrackStartError'\n // ];\n\n const constraintsErrors = ['OverconstrainedError', 'ConstraintNotSatisfiedError'];\n\n const isErrorOfType = (errorsArr: string[]) => errorsArr.filter((err: string) => err === errorName).length > 0;\n\n if (isErrorOfType(permissionErrorNames)) {\n throw {errorCode: MediaRequestErrorCode.PermissionDenied, message: errorName};\n }\n\n if (isErrorOfType(constraintsErrors)) {\n throw {errorCode: MediaRequestErrorCode.Overconstrained, message: errorName};\n }\n\n throw {errorCode: MediaRequestErrorCode.GeneralError, message: errorName};\n }\n}\n\nfunction _constraintByType(value: any, type: ConstraintType): any {\n switch (type) {\n case ConstraintType.MIN:\n return {min: value};\n default:\n return {ideal: value};\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/LocalStreamManager.ts"],"names":[],"mappings":"AAOA,OAAO,EAAC,QAAQ,EAAC,MAAM,yBAAyB,CAAC;AAEjD,OAAO,EACH,iBAAiB,EACjB,qBAAqB,EACrB,2BAA2B,EAE3B,yBAAyB,EAE5B,MAAM,kBAAkB,CAAC;AAY1B,OAAO,CAAC,MAAM,CAAC;IACX,UAAU,MAAM;QACZ,qBAAqB,EAAE,QAAQ,CAAC,yBAAyB,CAAC,CAAC;QAC3D,wBAAwB,EAAE,QAAQ,CAAC,yBAAyB,CAAC,CAAC;QAC9D,2BAA2B,EAAE,QAAQ,CAAC,qBAAqB,CAAC,CAAC;QAC7D,0BAA0B,EAAE,OAAO,CAAC;KACvC;CACJ;AAeD,UAAU,eAAe;IACrB,KAAK,EAAE,QAAQ,CAAC;QAAE,IAAI,CAAC,EAAE,eAAe,CAAC;QAAC,KAAK,CAAC,EAAE,eAAe,CAAA;KAAE,CAAC,CAAC;IACrE,KAAK,EAAE,QAAQ,CAAC,eAAe,CAAC,CAAC;IACjC,YAAY,EAAE,MAAM,CAAC;CACxB;AAED,qBAAa,kBAAkB;IAC3B,OAAO,CAAC,WAAW,CAAoB;IACvC,OAAO,CAAC,eAAe,CAAgE;gBAE3E,WAAW,EAAE,iBAAiB;IAO1C,IAAI,cAAc,oBAEjB;IAED,kBAAkB,CAAC,WAAW,EAAE,qBAAqB,GAAG,OAAO,CAAC,yBAAyB,CAAC;IA2C1F,qBAAqB,CAAC,WAAW,EAAE,2BAA2B,GAAG,OAAO,CAAC,yBAAyB,CAAC;IA4CnG,sBAAsB,IAAI,OAAO,CAAC,IAAI,CAAC;IAuBvC,yBAAyB,IAAI,OAAO,CAAC,IAAI,CAAC;IAqB1C,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC;IAShC,OAAO,CAAC,0BAA0B;IAwDlC,OAAO,CAAC,6BAA6B;IAsBrC,OAAO,CAAC,mCAAmC;IAoD3C,iBAAiB,CAAC,cAAc,EAAE;QAAC,KAAK,EAAE,eAAe,EAAE,CAAC;QAAC,KAAK,EAAE,eAAe,EAAE,CAAA;KAAC;IAStF,OAAO,CAAC,oBAAoB;IAuE5B,OAAO,CAAC,wBAAwB;CAwCnC","file":"LocalStreamManager.d.ts","sourcesContent":["import assign from 'lodash/assign';\nimport get from 'lodash/get';\nimport last from 'lodash/last';\nimport first from 'lodash/first';\nimport cloneDeep from 'lodash/cloneDeep';\nimport {Promise} from 'bluebird';\n\nimport {Nullable} from '@techsee/techsee-common';\n\nimport {\n IMediaEnvironment,\n LocalMediaConstraints,\n LocalVideoStreamConstraints,\n MediaRequestFailResult,\n MediaRequestSuccessResult,\n VideoStreamResolution\n} from './MediaContracts';\n\nimport {\n CameraTypes,\n ConstraintType,\n DEFAULT_VIDEO_CONSTRAINT_TYPE,\n DEFAULT_VIDEO_RESOLUTION,\n LocalVideoSourceType,\n MediaRequestErrorCode\n} from './MediaConstants';\nimport {getMediaTracer} from './MediaUtils/MediaTracer';\n\ndeclare global {\n interface Window {\n latestUserMediaStream: Nullable<MediaRequestSuccessResult>;\n latestDesktopMediaStream: Nullable<MediaRequestSuccessResult>;\n latestLocalMediaConstraints: Nullable<LocalMediaConstraints>;\n mediaStreamAlreadyReplaced: boolean;\n }\n}\n\ndeclare const window: Window;\n\nwindow.latestUserMediaStream = null;\nlet userMediaPromise: Nullable<Promise<MediaRequestSuccessResult>> = null;\n\nwindow.latestDesktopMediaStream = null;\nlet desktopMediaPromise: Nullable<Promise<MediaRequestSuccessResult>> = null;\n\nwindow.mediaStreamAlreadyReplaced = false;\nwindow.latestLocalMediaConstraints = null;\n\nconst trace = getMediaTracer('LocalStreamManager');\n\ninterface IGroupedDevices {\n video: Nullable<{ back?: MediaDeviceInfo; front?: MediaDeviceInfo }>;\n audio: Nullable<MediaDeviceInfo>;\n camerasCount: number;\n}\n\nexport class LocalStreamManager {\n private environment: IMediaEnvironment;\n private _groupedDevices: IGroupedDevices = {video: null, audio: null, camerasCount: 0};\n\n constructor(environment: IMediaEnvironment) {\n this.environment = environment;\n\n this.parseMediaErrorThenThrow = this.parseMediaErrorThenThrow.bind(this);\n this.clearAllStreams = this.clearAllStreams.bind(this);\n }\n\n get groupedDevices() {\n return this._groupedDevices;\n }\n\n getUserMediaStream(constraints: LocalMediaConstraints): Promise<MediaRequestSuccessResult> {\n trace.info('getUserMediaStream', constraints);\n if (userMediaPromise) {\n return userMediaPromise;\n }\n\n if (window.latestUserMediaStream) {\n const videoTrack = window.latestUserMediaStream.mediaStream.getVideoTracks();\n\n if (videoTrack.length > 0 && videoTrack[0].readyState === 'live') {\n return Promise.resolve({...window.latestUserMediaStream, isNew: false});\n }\n\n this.destroyUserMediaStream();\n }\n\n userMediaPromise = new Promise((resolve, reject) => {\n const catchHandler = (err: any): void => {\n userMediaPromise = null;\n window.latestUserMediaStream = null;\n trace.error('getUserMedia error', err);\n reject(err);\n };\n\n try {\n this.getHighestResolutionStream(false, constraints)\n .then((streamResult: MediaRequestSuccessResult) => {\n userMediaPromise = null;\n window.latestUserMediaStream = streamResult;\n window.latestLocalMediaConstraints = cloneDeep(constraints);\n window.latestLocalMediaConstraints.audio = (streamResult.constraint && streamResult.constraint.audio) as boolean;\n\n resolve({...window.latestUserMediaStream, isNew: true});\n })\n .catch(catchHandler);\n } catch (err) {\n catchHandler(err);\n }\n });\n\n return userMediaPromise;\n }\n\n getDesktopMediaStream(constraints: LocalVideoStreamConstraints): Promise<MediaRequestSuccessResult> {\n if (desktopMediaPromise) {\n return desktopMediaPromise;\n }\n\n trace.info('getDesktopMediaStream', constraints);\n\n if (window.latestDesktopMediaStream) {\n const track = window.latestDesktopMediaStream.mediaStream.getVideoTracks();\n\n if (track.length > 0 && track[0].readyState === 'live') {\n //return Promise.resolve();\n return Promise.resolve({...window.latestDesktopMediaStream, isNew: false});\n }\n this.destroyDesktopMediaStream().catch((error: any) => {\n trace.error('Error destroying desktop media stream', error);\n });\n\n }\n\n desktopMediaPromise = new Promise((resolve, reject) => {\n const mediaCatchHandler = (err: any): void => {\n desktopMediaPromise = null;\n window.latestDesktopMediaStream = null;\n trace.error('getDisplayMedia error', err);\n reject(err);\n };\n\n try {\n this.getHighestResolutionStream(true, {video: constraints, audio: false})\n .then((streamResult: MediaRequestSuccessResult) => {\n desktopMediaPromise = null;\n window.latestDesktopMediaStream = streamResult;\n\n resolve({...window.latestDesktopMediaStream, isNew: true});\n }).catch(mediaCatchHandler);\n } catch (err) {\n mediaCatchHandler(err);\n }\n });\n\n return desktopMediaPromise;\n }\n\n destroyUserMediaStream(): Promise<void> {\n const streamResult = window.latestUserMediaStream;\n\n userMediaPromise = null;\n window.latestUserMediaStream = null;\n window.latestLocalMediaConstraints = null;\n window.mediaStreamAlreadyReplaced = false;\n\n if (streamResult && streamResult.mediaStream) {\n try {\n streamResult.mediaStream.getTracks().forEach((track: MediaStreamTrack) => {\n track.stop();\n });\n\n trace.info('destroyUserMediaStream - stop all tracks');\n } catch (e) {\n trace.info('destroyUserMediaStream - Failed to stop all tracks', e);\n }\n }\n\n return Promise.resolve();\n }\n\n destroyDesktopMediaStream(): Promise<void> {\n const streamResult = window.latestDesktopMediaStream;\n\n window.latestDesktopMediaStream = null;\n desktopMediaPromise = null;\n\n if (streamResult && streamResult.mediaStream) {\n try {\n streamResult.mediaStream.getTracks().forEach((track: MediaStreamTrack) => {\n track.stop();\n });\n\n trace.info('destroyDesktopMediaStream - stop all tracks');\n } catch (e) {\n trace.info('destroyDesktopMediaStream - Failed to stop all tracks', e);\n }\n }\n\n return Promise.resolve();\n }\n\n clearAllStreams(): Promise<void> {\n trace.info('LocalStreamManager Clearing all streams');\n\n return Promise.all([\n this.destroyDesktopMediaStream(),\n this.destroyUserMediaStream()\n ]).then(() => undefined);\n }\n\n private getHighestResolutionStream(isDesktopMedia: boolean, constraints?: LocalMediaConstraints): Promise<MediaRequestSuccessResult> {\n const constraintsCandidates = this.getParsedConstraints(isDesktopMedia, constraints);\n\n trace.info('getHighestResolutionStream - constraintsCandidates:', constraintsCandidates);\n\n if (constraintsCandidates.length === 0) {\n return Promise.reject(new Error('No constraints to retrieve the stream'));\n }\n\n return new Promise((resolve, reject) => {\n let lastSuccessfulResult: Nullable<MediaRequestSuccessResult> = null;\n let lastFailedResult: Nullable<MediaRequestFailResult> = null;\n let isStreamRequestFulfilled = false;\n\n (Promise as any).reduce(constraintsCandidates, (total: any, candidate: MediaStreamConstraints) => {\n if (isStreamRequestFulfilled) {\n return;\n }\n\n const constraintType = get(constraints, 'video.videoResolution.constraintType') || get(constraints, 'video.videoResolution[0].constraintType');\n\n return this.getStreamPromiseByParsedConstraints(candidate, isDesktopMedia)\n .then((stream: MediaStream) => {\n lastSuccessfulResult = {\n mediaStream: stream,\n constraint: candidate,\n constraintType,\n isNew: true\n };\n trace.info('getHighestResolutionStream Success', lastSuccessfulResult);\n isStreamRequestFulfilled = true;\n resolve(lastSuccessfulResult);\n })\n .catch((failResult: MediaRequestFailResult) => {\n lastFailedResult = failResult;\n\n if (lastFailedResult.errorCode === MediaRequestErrorCode.PermissionDenied) {\n isStreamRequestFulfilled = true;\n reject(lastFailedResult);\n }\n });\n }, 0)\n .then(() => {\n if (!isStreamRequestFulfilled) {\n if (!lastFailedResult) {\n lastFailedResult = {\n errorCode: MediaRequestErrorCode.GeneralError,\n message: 'Suitable stream cannot be created'\n };\n }\n reject(lastFailedResult);\n }\n });\n });\n }\n\n private getUserMediaStreamMediaDevice(constraints: MediaStreamConstraints, isDesktopMedia: boolean) {\n let streamPromise = null;\n\n if (!isDesktopMedia) {\n streamPromise = navigator.mediaDevices.getUserMedia(constraints);\n } else {\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n //@ts-ignore\n streamPromise = navigator.mediaDevices.getDisplayMedia\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n //@ts-ignore\n ? navigator.mediaDevices.getDisplayMedia(constraints)\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n //@ts-ignore\n : navigator.getDisplayMedia(constraints);\n }\n\n return streamPromise;\n }\n\n // eslint-disable-next-line consistent-return,@typescript-eslint/ban-ts-comment\n // @ts-ignore\n private getStreamPromiseByParsedConstraints(constraints: MediaStreamConstraints, isDesktopMedia: boolean): Promise<MediaStream> {\n trace.info('getStreamPromiseByParsedConstraints', constraints);\n\n try {\n return this.getUserMediaStreamMediaDevice(constraints, isDesktopMedia).catch((err: any) => {\n let streamPromise = null;\n\n trace.info('getStreamPromiseByParsedConstraints - get user stream error', err.name);\n\n // Android (Galaxy esp.) have a bug that when using facingMode it might cause NotReadableError. So\n // we should try again but without facingMode. The exception to the rule is when we don't have specific\n // device to use (like in IOS13 bug, as can be seen in MediaServiceBase.ts), in that case, we might end\n // up using the front camera, which is a privacy concern and the preference is to fallback from video\n if (err && (err.name === 'NotReadableError') && get(constraints, 'video.facingMode') &&\n get(constraints, 'video.deviceId')) {\n\n const newConstraints = constraints;\n\n trace.info(`getStreamPromiseByParsedConstraints - NotReadableError - Failed to get video user media stream with facingMode=${get(constraints, 'video.facingMode')}`, err.name);\n\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n delete newConstraints.video.facingMode;\n ((newConstraints.video as MediaTrackConstraints).deviceId as ConstrainDOMStringParameters) = {\n exact: (constraints.video as MediaTrackConstraints).deviceId\n } as any as ConstrainDOMStringParameters;\n\n streamPromise = this.getStreamPromiseByParsedConstraints(newConstraints, isDesktopMedia);\n } else if (err && err.name && constraints.audio && !constraints.video) {\n trace.info('getStreamPromiseByParsedConstraints - audioStreamFailed - Failed to get audio user media stream', err.name);\n\n return this.parseMediaErrorThenThrow({name: 'audioStreamFailed'});\n } else if (err && err.name && constraints.audio) {\n const newConstraints = constraints;\n\n trace.info('getStreamPromiseByParsedConstraints - Failed to get video and audio user media stream, try to get video media stream only', err.name);\n\n newConstraints.audio = false;\n streamPromise = this.getStreamPromiseByParsedConstraints(newConstraints, isDesktopMedia);\n } else if (err && !streamPromise) {\n trace.info('getStreamPromiseByParsedConstraints - Failed to get video user media stream', err && err.name);\n\n streamPromise = Promise.reject(err);\n }\n\n return streamPromise && streamPromise.catch(this.parseMediaErrorThenThrow);\n });\n } catch (e) {\n this.parseMediaErrorThenThrow(e);\n }\n }\n\n setGroupedDevices(groupedDevices: {video: MediaDeviceInfo[]; audio: MediaDeviceInfo[]}) {\n trace.info('setGroupedDevices', groupedDevices);\n this._groupedDevices = {video: groupedDevices.video\n ? {[CameraTypes.BACK]: last(groupedDevices.video), [CameraTypes.FRONT]: first(groupedDevices.video)}\n : null,\n audio: last(groupedDevices.audio) || null,\n camerasCount: groupedDevices.video.length};\n }\n\n private getParsedConstraints(isDesktopMedia: boolean, streamConstraints?: LocalMediaConstraints): MediaStreamConstraints[] {\n const constraintCandidates: MediaStreamConstraints[] = [];\n\n //TODO - Alex: need to understand which constraints not compatible with screen share\n if (isDesktopMedia) {\n return [{video: true}];\n }\n\n if (!streamConstraints) {\n return constraintCandidates;\n }\n\n const baseConstraints: MediaStreamConstraints = {};\n\n baseConstraints.audio = typeof streamConstraints.audio === 'boolean' ? streamConstraints.audio : undefined;\n\n if (!streamConstraints.video) {\n return [baseConstraints];\n }\n\n const cameraType = (streamConstraints.video !== 'boolean') &&\n (streamConstraints.video as LocalVideoStreamConstraints).videoSourceType;\n\n baseConstraints.video = {\n facingMode: cameraType && cameraType === LocalVideoSourceType.CAMERA_FRONT\n ? 'user'\n : 'environment',\n frameRate: {ideal: 15, max: 30}\n };\n\n const deviceId = get(this._groupedDevices, `video.${cameraType === LocalVideoSourceType.CAMERA_FRONT\n ? CameraTypes.FRONT\n : CameraTypes.BACK}.deviceId`);\n\n if (deviceId) {\n baseConstraints.video.deviceId = deviceId;\n\n if (this._groupedDevices.camerasCount > 1) {\n baseConstraints.video.facingMode = {exact: baseConstraints.video.facingMode} as any as ConstrainDOMStringParameters;\n }\n }\n\n const assignConstraint = (videoResolution: VideoStreamResolution): void => {\n const [width, height] = videoResolution.resolution.split('x');\n const constraintCandidate = assign({}, baseConstraints);\n\n constraintCandidate.video = assign({}, baseConstraints.video, {\n width: _constraintByType(width, videoResolution.constraintType),\n height: _constraintByType(height, videoResolution.constraintType)\n });\n constraintCandidates.push(constraintCandidate);\n };\n\n if ((baseConstraints.video && typeof streamConstraints.video === 'boolean') ||\n !((streamConstraints.video as LocalVideoStreamConstraints).videoResolution instanceof Array)) {\n\n const defaultResolution: VideoStreamResolution = {\n resolution: DEFAULT_VIDEO_RESOLUTION,\n constraintType: DEFAULT_VIDEO_CONSTRAINT_TYPE\n };\n\n assignConstraint(defaultResolution);\n\n return constraintCandidates;\n }\n\n (streamConstraints.video as any).videoResolution.forEach(assignConstraint);\n\n return constraintCandidates;\n }\n\n private parseMediaErrorThenThrow(error: any): MediaRequestFailResult {\n if (error && error.errorCode) {\n throw error;\n }\n\n trace.error('Get media stream error.', error);\n const errorName = error && error.name ? error.name : '';\n\n const permissionErrorNames = [\n 'NotAllowedError',\n 'PermissionDismissedError',\n 'PermissionDeniedError'\n\n ];\n\n // const generalError = [\n // 'NotFoundError',\n // 'DevicesNotFoundError',\n // 'NotReadableError',\n // 'TrackStartError'\n // ];\n\n const constraintsErrors = [\n 'OverconstrainedError',\n 'ConstraintNotSatisfiedError'\n\n ];\n\n const isErrorOfType = (errorsArr: string[]) => errorsArr.filter((err: string) => err === errorName).length > 0;\n\n if (isErrorOfType(permissionErrorNames)) {\n throw {errorCode: MediaRequestErrorCode.PermissionDenied, message: errorName};\n }\n\n if (isErrorOfType(constraintsErrors)) {\n throw {errorCode: MediaRequestErrorCode.Overconstrained, message: errorName};\n }\n\n throw {errorCode: MediaRequestErrorCode.GeneralError, message: errorName};\n }\n}\n\nfunction _constraintByType(value: any, type: ConstraintType): any {\n switch (type) {\n case ConstraintType.MIN:\n return {min: value};\n default:\n return {ideal: value};\n }\n}\n"]}
|
|
@@ -25,9 +25,7 @@ var __importDefault = void 0 && (void 0).__importDefault || function (mod) {
|
|
|
25
25
|
Object.defineProperty(exports, "__esModule", {
|
|
26
26
|
value: true
|
|
27
27
|
});
|
|
28
|
-
exports.LocalStreamManager = void 0;
|
|
29
|
-
|
|
30
|
-
/*eslint-disable operator-linebreak */
|
|
28
|
+
exports.LocalStreamManager = void 0;
|
|
31
29
|
|
|
32
30
|
var assign_1 = __importDefault(require("lodash/assign"));
|
|
33
31
|
|
|
@@ -279,15 +277,17 @@ function () {
|
|
|
279
277
|
} else {
|
|
280
278
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
281
279
|
//@ts-ignore
|
|
282
|
-
streamPromise = navigator.mediaDevices.getDisplayMedia
|
|
280
|
+
streamPromise = navigator.mediaDevices.getDisplayMedia // eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
283
281
|
//@ts-ignore
|
|
284
|
-
navigator.mediaDevices.getDisplayMedia(constraints)
|
|
282
|
+
? navigator.mediaDevices.getDisplayMedia(constraints) // eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
285
283
|
//@ts-ignore
|
|
286
|
-
navigator.getDisplayMedia(constraints);
|
|
284
|
+
: navigator.getDisplayMedia(constraints);
|
|
287
285
|
}
|
|
288
286
|
|
|
289
287
|
return streamPromise;
|
|
290
|
-
};
|
|
288
|
+
}; // eslint-disable-next-line consistent-return,@typescript-eslint/ban-ts-comment
|
|
289
|
+
// @ts-ignore
|
|
290
|
+
|
|
291
291
|
|
|
292
292
|
LocalStreamManager.prototype.getStreamPromiseByParsedConstraints = function (constraints, isDesktopMedia) {
|
|
293
293
|
var _this = this;
|
|
@@ -330,8 +330,7 @@ function () {
|
|
|
330
330
|
return streamPromise && streamPromise["catch"](_this.parseMediaErrorThenThrow);
|
|
331
331
|
});
|
|
332
332
|
} catch (e) {
|
|
333
|
-
|
|
334
|
-
return this.parseMediaErrorThenThrow(e);
|
|
333
|
+
this.parseMediaErrorThenThrow(e);
|
|
335
334
|
}
|
|
336
335
|
};
|
|
337
336
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["LocalStreamManager.js","../src/LocalStreamManager.ts"],"names":["__assign","Object","assign","t","s","i","n","arguments","length","p","prototype","hasOwnProperty","call","apply","__importDefault","mod","__esModule","defineProperty","exports","value","LocalStreamManager","assign_1","require","get_1","last_1","first_1","cloneDeep_1","bluebird_1","MediaConstants_1","MediaTracer_1","window","latestUserMediaStream","userMediaPromise","latestDesktopMediaStream","desktopMediaPromise","mediaStreamAlreadyReplaced","latestLocalMediaConstraints","trace","getMediaTracer","environment","_groupedDevices","video","audio","camerasCount","parseMediaErrorThenThrow","bind","clearAllStreams","get","enumerable","configurable","getUserMediaStream","constraints","_this","info","videoTrack","mediaStream","getVideoTracks","readyState","Promise","resolve","isNew","destroyUserMediaStream","reject","catchHandler","err","error","getHighestResolutionStream","then","streamResult","constraint","getDesktopMediaStream","track","destroyDesktopMediaStream","mediaCatchHandler","getTracks","forEach","stop","e","all","undefined","isDesktopMedia","constraintsCandidates","getParsedConstraints","Error","lastSuccessfulResult","lastFailedResult","isStreamRequestFulfilled","reduce","total","candidate","constraintType","getStreamPromiseByParsedConstraints","stream","failResult","errorCode","MediaRequestErrorCode","PermissionDenied","GeneralError","message","getUserMediaStreamMediaDevice","streamPromise","navigator","mediaDevices","getUserMedia","getDisplayMedia","name","newConstraints","facingMode","deviceId","exact","setGroupedDevices","groupedDevices","_a","CameraTypes","BACK","FRONT","streamConstraints","constraintCandidates","baseConstraints","cameraType","videoSourceType","LocalVideoSourceType","CAMERA_FRONT","frameRate","ideal","max","assignConstraint","videoResolution","resolution","split","width","height","constraintCandidate","_constraintByType","push","Array","defaultResolution","DEFAULT_VIDEO_RESOLUTION","DEFAULT_VIDEO_CONSTRAINT_TYPE","errorName","permissionErrorNames","constraintsErrors","isErrorOfType","errorsArr","filter","Overconstrained","type","ConstraintType","MIN","min"],"mappings":"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","file":"LocalStreamManager.js","sourcesContent":["\"use strict\";\nvar __assign = (this && this.__assign) || function () {\n __assign = Object.assign || function(t) {\n for (var s, i = 1, n = arguments.length; i < n; i++) {\n s = arguments[i];\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))\n t[p] = s[p];\n }\n return t;\n };\n return __assign.apply(this, arguments);\n};\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.LocalStreamManager = void 0;\n// eslint-disable-next-line eslint-comments/disable-enable-pair\n/*eslint-disable operator-linebreak */\nvar assign_1 = __importDefault(require(\"lodash/assign\"));\nvar get_1 = __importDefault(require(\"lodash/get\"));\nvar last_1 = __importDefault(require(\"lodash/last\"));\nvar first_1 = __importDefault(require(\"lodash/first\"));\nvar cloneDeep_1 = __importDefault(require(\"lodash/cloneDeep\"));\nvar bluebird_1 = require(\"bluebird\");\nvar MediaConstants_1 = require(\"./MediaConstants\");\nvar MediaTracer_1 = require(\"./MediaUtils/MediaTracer\");\nwindow.latestUserMediaStream = null;\nvar userMediaPromise = null;\nwindow.latestDesktopMediaStream = null;\nvar desktopMediaPromise = null;\nwindow.mediaStreamAlreadyReplaced = false;\nwindow.latestLocalMediaConstraints = null;\nvar trace = MediaTracer_1.getMediaTracer('LocalStreamManager');\nvar LocalStreamManager = /** @class */ (function () {\n function LocalStreamManager(environment) {\n this._groupedDevices = { video: null, audio: null, camerasCount: 0 };\n this.environment = environment;\n this.parseMediaErrorThenThrow = this.parseMediaErrorThenThrow.bind(this);\n this.clearAllStreams = this.clearAllStreams.bind(this);\n }\n Object.defineProperty(LocalStreamManager.prototype, \"groupedDevices\", {\n get: function () {\n return this._groupedDevices;\n },\n enumerable: false,\n configurable: true\n });\n LocalStreamManager.prototype.getUserMediaStream = function (constraints) {\n var _this = this;\n trace.info('getUserMediaStream', constraints);\n if (userMediaPromise) {\n return userMediaPromise;\n }\n if (window.latestUserMediaStream) {\n var videoTrack = window.latestUserMediaStream.mediaStream.getVideoTracks();\n if (videoTrack.length > 0 && videoTrack[0].readyState === 'live') {\n return bluebird_1.Promise.resolve(__assign(__assign({}, window.latestUserMediaStream), { isNew: false }));\n }\n this.destroyUserMediaStream();\n }\n userMediaPromise = new bluebird_1.Promise(function (resolve, reject) {\n var catchHandler = function (err) {\n userMediaPromise = null;\n window.latestUserMediaStream = null;\n trace.error('getUserMedia error', err);\n reject(err);\n };\n try {\n _this.getHighestResolutionStream(false, constraints)\n .then(function (streamResult) {\n userMediaPromise = null;\n window.latestUserMediaStream = streamResult;\n window.latestLocalMediaConstraints = cloneDeep_1.default(constraints);\n window.latestLocalMediaConstraints.audio = (streamResult.constraint &&\n streamResult.constraint.audio);\n resolve(__assign(__assign({}, window.latestUserMediaStream), { isNew: true }));\n })\n .catch(catchHandler);\n }\n catch (err) {\n catchHandler(err);\n }\n });\n return userMediaPromise;\n };\n LocalStreamManager.prototype.getDesktopMediaStream = function (constraints) {\n var _this = this;\n if (desktopMediaPromise) {\n return desktopMediaPromise;\n }\n trace.info('getDesktopMediaStream', constraints);\n if (window.latestDesktopMediaStream) {\n var track = window.latestDesktopMediaStream.mediaStream.getVideoTracks();\n if (track.length > 0 && track[0].readyState === 'live') {\n //return Promise.resolve();\n return bluebird_1.Promise.resolve(__assign(__assign({}, window.latestDesktopMediaStream), { isNew: false }));\n }\n this.destroyDesktopMediaStream().catch(function (error) {\n trace.error('Error destroying desktop media stream', error);\n });\n }\n desktopMediaPromise = new bluebird_1.Promise(function (resolve, reject) {\n var mediaCatchHandler = function (err) {\n desktopMediaPromise = null;\n window.latestDesktopMediaStream = null;\n trace.error('getDisplayMedia error', err);\n reject(err);\n };\n try {\n _this.getHighestResolutionStream(true, { video: constraints, audio: false })\n .then(function (streamResult) {\n desktopMediaPromise = null;\n window.latestDesktopMediaStream = streamResult;\n resolve(__assign(__assign({}, window.latestDesktopMediaStream), { isNew: true }));\n })\n .catch(mediaCatchHandler);\n }\n catch (err) {\n mediaCatchHandler(err);\n }\n });\n return desktopMediaPromise;\n };\n LocalStreamManager.prototype.destroyUserMediaStream = function () {\n var streamResult = window.latestUserMediaStream;\n userMediaPromise = null;\n window.latestUserMediaStream = null;\n window.latestLocalMediaConstraints = null;\n window.mediaStreamAlreadyReplaced = false;\n if (streamResult && streamResult.mediaStream) {\n try {\n streamResult.mediaStream.getTracks().forEach(function (track) {\n track.stop();\n });\n trace.info('destroyUserMediaStream - stop all tracks');\n }\n catch (e) {\n trace.info('destroyUserMediaStream - Failed to stop all tracks', e);\n }\n }\n return bluebird_1.Promise.resolve();\n };\n LocalStreamManager.prototype.destroyDesktopMediaStream = function () {\n var streamResult = window.latestDesktopMediaStream;\n window.latestDesktopMediaStream = null;\n desktopMediaPromise = null;\n if (streamResult && streamResult.mediaStream) {\n try {\n streamResult.mediaStream.getTracks().forEach(function (track) {\n track.stop();\n });\n trace.info('destroyDesktopMediaStream - stop all tracks');\n }\n catch (e) {\n trace.info('destroyDesktopMediaStream - Failed to stop all tracks', e);\n }\n }\n return bluebird_1.Promise.resolve();\n };\n LocalStreamManager.prototype.clearAllStreams = function () {\n trace.info('LocalStreamManager Clearing all streams');\n return bluebird_1.Promise.all([this.destroyDesktopMediaStream(), this.destroyUserMediaStream()]).then(function () { return undefined; });\n };\n LocalStreamManager.prototype.getHighestResolutionStream = function (isDesktopMedia, constraints) {\n var _this = this;\n var constraintsCandidates = this.getParsedConstraints(isDesktopMedia, constraints);\n trace.info('getHighestResolutionStream - constraintsCandidates:', constraintsCandidates);\n if (constraintsCandidates.length === 0) {\n return bluebird_1.Promise.reject(new Error('No constraints to retrieve the stream'));\n }\n return new bluebird_1.Promise(function (resolve, reject) {\n var lastSuccessfulResult = null;\n var lastFailedResult = null;\n var isStreamRequestFulfilled = false;\n bluebird_1.Promise\n .reduce(constraintsCandidates, function (total, candidate) {\n if (isStreamRequestFulfilled) {\n return;\n }\n var constraintType = get_1.default(constraints, 'video.videoResolution.constraintType') ||\n get_1.default(constraints, 'video.videoResolution[0].constraintType');\n return _this.getStreamPromiseByParsedConstraints(candidate, isDesktopMedia)\n .then(function (stream) {\n lastSuccessfulResult = {\n mediaStream: stream,\n constraint: candidate,\n constraintType: constraintType,\n isNew: true\n };\n trace.info('getHighestResolutionStream Success', lastSuccessfulResult);\n isStreamRequestFulfilled = true;\n resolve(lastSuccessfulResult);\n })\n .catch(function (failResult) {\n lastFailedResult = failResult;\n if (lastFailedResult.errorCode === MediaConstants_1.MediaRequestErrorCode.PermissionDenied) {\n isStreamRequestFulfilled = true;\n reject(lastFailedResult);\n }\n });\n }, 0)\n .then(function () {\n if (!isStreamRequestFulfilled) {\n if (!lastFailedResult) {\n lastFailedResult = {\n errorCode: MediaConstants_1.MediaRequestErrorCode.GeneralError,\n message: 'Suitable stream cannot be created'\n };\n }\n reject(lastFailedResult);\n }\n });\n });\n };\n LocalStreamManager.prototype.getUserMediaStreamMediaDevice = function (constraints, isDesktopMedia) {\n var streamPromise = null;\n if (!isDesktopMedia) {\n streamPromise = navigator.mediaDevices.getUserMedia(constraints);\n }\n else {\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n //@ts-ignore\n streamPromise = navigator.mediaDevices.getDisplayMedia\n ? // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n //@ts-ignore\n navigator.mediaDevices.getDisplayMedia(constraints)\n : // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n //@ts-ignore\n navigator.getDisplayMedia(constraints);\n }\n return streamPromise;\n };\n LocalStreamManager.prototype.getStreamPromiseByParsedConstraints = function (constraints, isDesktopMedia) {\n var _this = this;\n trace.info('getStreamPromiseByParsedConstraints', constraints);\n try {\n return this.getUserMediaStreamMediaDevice(constraints, isDesktopMedia).catch(function (err) {\n var streamPromise = null;\n trace.info('getStreamPromiseByParsedConstraints - get user stream error', err.name);\n // Android (Galaxy esp.) have a bug that when using facingMode it might cause NotReadableError. So\n // we should try again but without facingMode. The exception to the rule is when we don't have specific\n // device to use (like in IOS13 bug, as can be seen in MediaServiceBase.ts), in that case, we might end\n // up using the front camera, which is a privacy concern and the preference is to fallback from video\n if (err &&\n err.name === 'NotReadableError' &&\n get_1.default(constraints, 'video.facingMode') &&\n get_1.default(constraints, 'video.deviceId')) {\n var newConstraints = constraints;\n trace.info(\"getStreamPromiseByParsedConstraints - NotReadableError - Failed to get video user media stream with facingMode=\" + get_1.default(constraints, 'video.facingMode'), err.name);\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n delete newConstraints.video.facingMode;\n newConstraints.video.deviceId = {\n exact: constraints.video.deviceId\n };\n streamPromise = _this.getStreamPromiseByParsedConstraints(newConstraints, isDesktopMedia);\n }\n else if (err && err.name && constraints.audio && !constraints.video) {\n trace.info('getStreamPromiseByParsedConstraints - audioStreamFailed - Failed to get audio user media stream', err.name);\n return _this.parseMediaErrorThenThrow({ name: 'audioStreamFailed' });\n }\n else if (err && err.name && constraints.audio) {\n var newConstraints = constraints;\n trace.info('getStreamPromiseByParsedConstraints - Failed to get video and audio user media stream, try to get video media stream only', err.name);\n newConstraints.audio = false;\n streamPromise = _this.getStreamPromiseByParsedConstraints(newConstraints, isDesktopMedia);\n }\n else if (err && !streamPromise) {\n trace.info('getStreamPromiseByParsedConstraints - Failed to get video user media stream', err && err.name);\n streamPromise = bluebird_1.Promise.reject(err);\n }\n return streamPromise && streamPromise.catch(_this.parseMediaErrorThenThrow);\n });\n }\n catch (e) {\n // @ts-ignore\n return this.parseMediaErrorThenThrow(e);\n }\n };\n LocalStreamManager.prototype.setGroupedDevices = function (groupedDevices) {\n var _a;\n trace.info('setGroupedDevices', groupedDevices);\n this._groupedDevices = {\n video: groupedDevices.video\n ? (_a = {}, _a[MediaConstants_1.CameraTypes.BACK] = last_1.default(groupedDevices.video), _a[MediaConstants_1.CameraTypes.FRONT] = first_1.default(groupedDevices.video), _a) : null,\n audio: last_1.default(groupedDevices.audio) || null,\n camerasCount: groupedDevices.video.length\n };\n };\n LocalStreamManager.prototype.getParsedConstraints = function (isDesktopMedia, streamConstraints) {\n var constraintCandidates = [];\n //TODO - Alex: need to understand which constraints not compatible with screen share\n if (isDesktopMedia) {\n return [{ video: true }];\n }\n if (!streamConstraints) {\n return constraintCandidates;\n }\n var baseConstraints = {};\n baseConstraints.audio = typeof streamConstraints.audio === 'boolean' ? streamConstraints.audio : undefined;\n if (!streamConstraints.video) {\n return [baseConstraints];\n }\n var cameraType = streamConstraints.video !== 'boolean' &&\n streamConstraints.video.videoSourceType;\n baseConstraints.video = {\n facingMode: cameraType && cameraType === MediaConstants_1.LocalVideoSourceType.CAMERA_FRONT ? 'user' : 'environment',\n frameRate: { ideal: 15, max: 30 }\n };\n var deviceId = get_1.default(this._groupedDevices, \"video.\" + (cameraType === MediaConstants_1.LocalVideoSourceType.CAMERA_FRONT ? MediaConstants_1.CameraTypes.FRONT : MediaConstants_1.CameraTypes.BACK) + \".deviceId\");\n if (deviceId) {\n baseConstraints.video.deviceId = deviceId;\n if (this._groupedDevices.camerasCount > 1) {\n baseConstraints.video.facingMode = {\n exact: baseConstraints.video.facingMode\n };\n }\n }\n var assignConstraint = function (videoResolution) {\n var _a = videoResolution.resolution.split('x'), width = _a[0], height = _a[1];\n var constraintCandidate = assign_1.default({}, baseConstraints);\n constraintCandidate.video = assign_1.default({}, baseConstraints.video, {\n width: _constraintByType(width, videoResolution.constraintType),\n height: _constraintByType(height, videoResolution.constraintType)\n });\n constraintCandidates.push(constraintCandidate);\n };\n if ((baseConstraints.video && typeof streamConstraints.video === 'boolean') ||\n !(streamConstraints.video.videoResolution instanceof Array)) {\n var defaultResolution = {\n resolution: MediaConstants_1.DEFAULT_VIDEO_RESOLUTION,\n constraintType: MediaConstants_1.DEFAULT_VIDEO_CONSTRAINT_TYPE\n };\n assignConstraint(defaultResolution);\n return constraintCandidates;\n }\n streamConstraints.video.videoResolution.forEach(assignConstraint);\n return constraintCandidates;\n };\n LocalStreamManager.prototype.parseMediaErrorThenThrow = function (error) {\n if (error && error.errorCode) {\n throw error;\n }\n trace.error('Get media stream error.', error);\n var errorName = error && error.name ? error.name : '';\n var permissionErrorNames = ['NotAllowedError', 'PermissionDismissedError', 'PermissionDeniedError'];\n // const generalError = [\n // 'NotFoundError',\n // 'DevicesNotFoundError',\n // 'NotReadableError',\n // 'TrackStartError'\n // ];\n var constraintsErrors = ['OverconstrainedError', 'ConstraintNotSatisfiedError'];\n var isErrorOfType = function (errorsArr) { return errorsArr.filter(function (err) { return err === errorName; }).length > 0; };\n if (isErrorOfType(permissionErrorNames)) {\n throw { errorCode: MediaConstants_1.MediaRequestErrorCode.PermissionDenied, message: errorName };\n }\n if (isErrorOfType(constraintsErrors)) {\n throw { errorCode: MediaConstants_1.MediaRequestErrorCode.Overconstrained, message: errorName };\n }\n throw { errorCode: MediaConstants_1.MediaRequestErrorCode.GeneralError, message: errorName };\n };\n return LocalStreamManager;\n}());\nexports.LocalStreamManager = LocalStreamManager;\nfunction _constraintByType(value, type) {\n switch (type) {\n case MediaConstants_1.ConstraintType.MIN:\n return { min: value };\n default:\n return { ideal: value };\n }\n}\n\n//# sourceMappingURL=LocalStreamManager.js.map\n","// eslint-disable-next-line eslint-comments/disable-enable-pair\n/*eslint-disable operator-linebreak */\nimport assign from 'lodash/assign';\nimport get from 'lodash/get';\nimport last from 'lodash/last';\nimport first from 'lodash/first';\nimport cloneDeep from 'lodash/cloneDeep';\nimport {Promise} from 'bluebird';\n\nimport {Nullable} from '@techsee/techsee-common';\n\nimport {\n IMediaEnvironment,\n LocalMediaConstraints,\n LocalVideoStreamConstraints,\n MediaRequestFailResult,\n MediaRequestSuccessResult,\n VideoStreamResolution\n} from './MediaContracts';\n\nimport {\n CameraTypes,\n ConstraintType,\n DEFAULT_VIDEO_CONSTRAINT_TYPE,\n DEFAULT_VIDEO_RESOLUTION,\n LocalVideoSourceType,\n MediaRequestErrorCode\n} from './MediaConstants';\nimport {getMediaTracer} from './MediaUtils/MediaTracer';\n\ndeclare global {\n interface Window {\n latestUserMediaStream: Nullable<MediaRequestSuccessResult>;\n latestDesktopMediaStream: Nullable<MediaRequestSuccessResult>;\n latestLocalMediaConstraints: Nullable<LocalMediaConstraints>;\n mediaStreamAlreadyReplaced: boolean;\n }\n}\n\ndeclare const window: Window;\n\nwindow.latestUserMediaStream = null;\nlet userMediaPromise: Nullable<Promise<MediaRequestSuccessResult>> = null;\n\nwindow.latestDesktopMediaStream = null;\nlet desktopMediaPromise: Nullable<Promise<MediaRequestSuccessResult>> = null;\n\nwindow.mediaStreamAlreadyReplaced = false;\nwindow.latestLocalMediaConstraints = null;\n\nconst trace = getMediaTracer('LocalStreamManager');\n\ninterface IGroupedDevices {\n video: Nullable<{back?: MediaDeviceInfo; front?: MediaDeviceInfo}>;\n audio: Nullable<MediaDeviceInfo>;\n camerasCount: number;\n}\n\nexport class LocalStreamManager {\n private environment: IMediaEnvironment;\n\n private _groupedDevices: IGroupedDevices = {video: null, audio: null, camerasCount: 0};\n\n constructor(environment: IMediaEnvironment) {\n this.environment = environment;\n\n this.parseMediaErrorThenThrow = this.parseMediaErrorThenThrow.bind(this);\n this.clearAllStreams = this.clearAllStreams.bind(this);\n }\n\n get groupedDevices() {\n return this._groupedDevices;\n }\n\n getUserMediaStream(constraints: LocalMediaConstraints): Promise<MediaRequestSuccessResult> {\n trace.info('getUserMediaStream', constraints);\n if (userMediaPromise) {\n return userMediaPromise;\n }\n\n if (window.latestUserMediaStream) {\n const videoTrack = window.latestUserMediaStream.mediaStream.getVideoTracks();\n\n if (videoTrack.length > 0 && videoTrack[0].readyState === 'live') {\n return Promise.resolve({...window.latestUserMediaStream, isNew: false});\n }\n\n this.destroyUserMediaStream();\n }\n\n userMediaPromise = new Promise((resolve, reject) => {\n const catchHandler = (err: any): void => {\n userMediaPromise = null;\n window.latestUserMediaStream = null;\n trace.error('getUserMedia error', err);\n reject(err);\n };\n\n try {\n this.getHighestResolutionStream(false, constraints)\n .then((streamResult: MediaRequestSuccessResult) => {\n userMediaPromise = null;\n window.latestUserMediaStream = streamResult;\n window.latestLocalMediaConstraints = cloneDeep(constraints);\n window.latestLocalMediaConstraints.audio = (streamResult.constraint &&\n streamResult.constraint.audio) as boolean;\n\n resolve({...window.latestUserMediaStream, isNew: true});\n })\n .catch(catchHandler);\n } catch (err) {\n catchHandler(err);\n }\n });\n\n return userMediaPromise;\n }\n\n getDesktopMediaStream(constraints: LocalVideoStreamConstraints): Promise<MediaRequestSuccessResult> {\n if (desktopMediaPromise) {\n return desktopMediaPromise;\n }\n\n trace.info('getDesktopMediaStream', constraints);\n\n if (window.latestDesktopMediaStream) {\n const track = window.latestDesktopMediaStream.mediaStream.getVideoTracks();\n\n if (track.length > 0 && track[0].readyState === 'live') {\n //return Promise.resolve();\n return Promise.resolve({...window.latestDesktopMediaStream, isNew: false});\n }\n this.destroyDesktopMediaStream().catch((error: any) => {\n trace.error('Error destroying desktop media stream', error);\n });\n }\n\n desktopMediaPromise = new Promise((resolve, reject) => {\n const mediaCatchHandler = (err: any): void => {\n desktopMediaPromise = null;\n window.latestDesktopMediaStream = null;\n trace.error('getDisplayMedia error', err);\n reject(err);\n };\n\n try {\n this.getHighestResolutionStream(true, {video: constraints, audio: false})\n .then((streamResult: MediaRequestSuccessResult) => {\n desktopMediaPromise = null;\n window.latestDesktopMediaStream = streamResult;\n\n resolve({...window.latestDesktopMediaStream, isNew: true});\n })\n .catch(mediaCatchHandler);\n } catch (err) {\n mediaCatchHandler(err);\n }\n });\n\n return desktopMediaPromise;\n }\n\n destroyUserMediaStream(): Promise<void> {\n const streamResult = window.latestUserMediaStream;\n\n userMediaPromise = null;\n window.latestUserMediaStream = null;\n window.latestLocalMediaConstraints = null;\n window.mediaStreamAlreadyReplaced = false;\n\n if (streamResult && streamResult.mediaStream) {\n try {\n streamResult.mediaStream.getTracks().forEach((track: MediaStreamTrack) => {\n track.stop();\n });\n\n trace.info('destroyUserMediaStream - stop all tracks');\n } catch (e) {\n trace.info('destroyUserMediaStream - Failed to stop all tracks', e);\n }\n }\n\n return Promise.resolve();\n }\n\n destroyDesktopMediaStream(): Promise<void> {\n const streamResult = window.latestDesktopMediaStream;\n\n window.latestDesktopMediaStream = null;\n desktopMediaPromise = null;\n\n if (streamResult && streamResult.mediaStream) {\n try {\n streamResult.mediaStream.getTracks().forEach((track: MediaStreamTrack) => {\n track.stop();\n });\n\n trace.info('destroyDesktopMediaStream - stop all tracks');\n } catch (e) {\n trace.info('destroyDesktopMediaStream - Failed to stop all tracks', e);\n }\n }\n\n return Promise.resolve();\n }\n\n clearAllStreams(): Promise<void> {\n trace.info('LocalStreamManager Clearing all streams');\n\n return Promise.all([this.destroyDesktopMediaStream(), this.destroyUserMediaStream()]).then(() => undefined);\n }\n\n private getHighestResolutionStream(\n isDesktopMedia: boolean,\n constraints?: LocalMediaConstraints\n ): Promise<MediaRequestSuccessResult> {\n const constraintsCandidates = this.getParsedConstraints(isDesktopMedia, constraints);\n\n trace.info('getHighestResolutionStream - constraintsCandidates:', constraintsCandidates);\n\n if (constraintsCandidates.length === 0) {\n return Promise.reject(new Error('No constraints to retrieve the stream'));\n }\n\n return new Promise((resolve, reject) => {\n let lastSuccessfulResult: Nullable<MediaRequestSuccessResult> = null;\n let lastFailedResult: Nullable<MediaRequestFailResult> = null;\n let isStreamRequestFulfilled = false;\n\n (Promise as any)\n .reduce(\n constraintsCandidates,\n (total: any, candidate: MediaStreamConstraints) => {\n if (isStreamRequestFulfilled) {\n return;\n }\n\n const constraintType =\n get(constraints, 'video.videoResolution.constraintType') ||\n get(constraints, 'video.videoResolution[0].constraintType');\n\n return this.getStreamPromiseByParsedConstraints(candidate, isDesktopMedia)\n .then((stream: MediaStream) => {\n lastSuccessfulResult = {\n mediaStream: stream,\n constraint: candidate,\n constraintType,\n isNew: true\n };\n trace.info('getHighestResolutionStream Success', lastSuccessfulResult);\n isStreamRequestFulfilled = true;\n resolve(lastSuccessfulResult);\n })\n .catch((failResult: MediaRequestFailResult) => {\n lastFailedResult = failResult;\n\n if (lastFailedResult.errorCode === MediaRequestErrorCode.PermissionDenied) {\n isStreamRequestFulfilled = true;\n reject(lastFailedResult);\n }\n });\n },\n 0\n )\n .then(() => {\n if (!isStreamRequestFulfilled) {\n if (!lastFailedResult) {\n lastFailedResult = {\n errorCode: MediaRequestErrorCode.GeneralError,\n message: 'Suitable stream cannot be created'\n };\n }\n reject(lastFailedResult);\n }\n });\n });\n }\n\n private getUserMediaStreamMediaDevice(constraints: MediaStreamConstraints, isDesktopMedia: boolean) {\n let streamPromise = null;\n\n if (!isDesktopMedia) {\n streamPromise = navigator.mediaDevices.getUserMedia(constraints);\n } else {\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n //@ts-ignore\n streamPromise = navigator.mediaDevices.getDisplayMedia\n ? // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n //@ts-ignore\n navigator.mediaDevices.getDisplayMedia(constraints)\n : // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n //@ts-ignore\n navigator.getDisplayMedia(constraints);\n }\n\n return streamPromise;\n }\n\n private getStreamPromiseByParsedConstraints(\n constraints: MediaStreamConstraints,\n isDesktopMedia: boolean\n ): Promise<MediaStream> {\n trace.info('getStreamPromiseByParsedConstraints', constraints);\n\n try {\n return this.getUserMediaStreamMediaDevice(constraints, isDesktopMedia).catch((err: any) => {\n let streamPromise = null;\n\n trace.info('getStreamPromiseByParsedConstraints - get user stream error', err.name);\n\n // Android (Galaxy esp.) have a bug that when using facingMode it might cause NotReadableError. So\n // we should try again but without facingMode. The exception to the rule is when we don't have specific\n // device to use (like in IOS13 bug, as can be seen in MediaServiceBase.ts), in that case, we might end\n // up using the front camera, which is a privacy concern and the preference is to fallback from video\n if (\n err &&\n err.name === 'NotReadableError' &&\n get(constraints, 'video.facingMode') &&\n get(constraints, 'video.deviceId')\n ) {\n const newConstraints = constraints;\n\n trace.info(\n `getStreamPromiseByParsedConstraints - NotReadableError - Failed to get video user media stream with facingMode=${get(\n constraints,\n 'video.facingMode'\n )}`,\n err.name\n );\n\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n delete newConstraints.video.facingMode;\n ((newConstraints.video as MediaTrackConstraints).deviceId as ConstrainDOMStringParameters) = {\n exact: (constraints.video as MediaTrackConstraints).deviceId\n } as any as ConstrainDOMStringParameters;\n\n streamPromise = this.getStreamPromiseByParsedConstraints(newConstraints, isDesktopMedia);\n } else if (err && err.name && constraints.audio && !constraints.video) {\n trace.info(\n 'getStreamPromiseByParsedConstraints - audioStreamFailed - Failed to get audio user media stream',\n err.name\n );\n\n return this.parseMediaErrorThenThrow({name: 'audioStreamFailed'});\n } else if (err && err.name && constraints.audio) {\n const newConstraints = constraints;\n\n trace.info(\n 'getStreamPromiseByParsedConstraints - Failed to get video and audio user media stream, try to get video media stream only',\n err.name\n );\n\n newConstraints.audio = false;\n streamPromise = this.getStreamPromiseByParsedConstraints(newConstraints, isDesktopMedia);\n } else if (err && !streamPromise) {\n trace.info(\n 'getStreamPromiseByParsedConstraints - Failed to get video user media stream',\n err && err.name\n );\n\n streamPromise = Promise.reject(err);\n }\n\n return streamPromise && streamPromise.catch(this.parseMediaErrorThenThrow);\n });\n } catch (e) {\n // @ts-ignore\n return this.parseMediaErrorThenThrow(e);\n }\n }\n\n setGroupedDevices(groupedDevices: {video: MediaDeviceInfo[]; audio: MediaDeviceInfo[]}) {\n trace.info('setGroupedDevices', groupedDevices);\n this._groupedDevices = {\n video: groupedDevices.video\n ? {[CameraTypes.BACK]: last(groupedDevices.video), [CameraTypes.FRONT]: first(groupedDevices.video)}\n : null,\n audio: last(groupedDevices.audio) || null,\n camerasCount: groupedDevices.video.length\n };\n }\n\n private getParsedConstraints(\n isDesktopMedia: boolean,\n streamConstraints?: LocalMediaConstraints\n ): MediaStreamConstraints[] {\n const constraintCandidates: MediaStreamConstraints[] = [];\n\n //TODO - Alex: need to understand which constraints not compatible with screen share\n if (isDesktopMedia) {\n return [{video: true}];\n }\n\n if (!streamConstraints) {\n return constraintCandidates;\n }\n\n const baseConstraints: MediaStreamConstraints = {};\n\n baseConstraints.audio = typeof streamConstraints.audio === 'boolean' ? streamConstraints.audio : undefined;\n\n if (!streamConstraints.video) {\n return [baseConstraints];\n }\n\n const cameraType =\n streamConstraints.video !== 'boolean' &&\n (streamConstraints.video as LocalVideoStreamConstraints).videoSourceType;\n\n baseConstraints.video = {\n facingMode: cameraType && cameraType === LocalVideoSourceType.CAMERA_FRONT ? 'user' : 'environment',\n frameRate: {ideal: 15, max: 30}\n };\n\n const deviceId = get(\n this._groupedDevices,\n `video.${cameraType === LocalVideoSourceType.CAMERA_FRONT ? CameraTypes.FRONT : CameraTypes.BACK}.deviceId`\n );\n\n if (deviceId) {\n baseConstraints.video.deviceId = deviceId;\n\n if (this._groupedDevices.camerasCount > 1) {\n baseConstraints.video.facingMode = {\n exact: baseConstraints.video.facingMode\n } as any as ConstrainDOMStringParameters;\n }\n }\n\n const assignConstraint = (videoResolution: VideoStreamResolution): void => {\n const [width, height] = videoResolution.resolution.split('x');\n const constraintCandidate = assign({}, baseConstraints);\n\n constraintCandidate.video = assign({}, baseConstraints.video, {\n width: _constraintByType(width, videoResolution.constraintType),\n height: _constraintByType(height, videoResolution.constraintType)\n });\n constraintCandidates.push(constraintCandidate);\n };\n\n if (\n (baseConstraints.video && typeof streamConstraints.video === 'boolean') ||\n !((streamConstraints.video as LocalVideoStreamConstraints).videoResolution instanceof Array)\n ) {\n const defaultResolution: VideoStreamResolution = {\n resolution: DEFAULT_VIDEO_RESOLUTION,\n constraintType: DEFAULT_VIDEO_CONSTRAINT_TYPE\n };\n\n assignConstraint(defaultResolution);\n\n return constraintCandidates;\n }\n\n (streamConstraints.video as any).videoResolution.forEach(assignConstraint);\n\n return constraintCandidates;\n }\n\n private parseMediaErrorThenThrow(error: any): MediaRequestFailResult {\n if (error && error.errorCode) {\n throw error;\n }\n\n trace.error('Get media stream error.', error);\n const errorName = error && error.name ? error.name : '';\n\n const permissionErrorNames = ['NotAllowedError', 'PermissionDismissedError', 'PermissionDeniedError'];\n\n // const generalError = [\n // 'NotFoundError',\n // 'DevicesNotFoundError',\n // 'NotReadableError',\n // 'TrackStartError'\n // ];\n\n const constraintsErrors = ['OverconstrainedError', 'ConstraintNotSatisfiedError'];\n\n const isErrorOfType = (errorsArr: string[]) => errorsArr.filter((err: string) => err === errorName).length > 0;\n\n if (isErrorOfType(permissionErrorNames)) {\n throw {errorCode: MediaRequestErrorCode.PermissionDenied, message: errorName};\n }\n\n if (isErrorOfType(constraintsErrors)) {\n throw {errorCode: MediaRequestErrorCode.Overconstrained, message: errorName};\n }\n\n throw {errorCode: MediaRequestErrorCode.GeneralError, message: errorName};\n }\n}\n\nfunction _constraintByType(value: any, type: ConstraintType): any {\n switch (type) {\n case ConstraintType.MIN:\n return {min: value};\n default:\n return {ideal: value};\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["LocalStreamManager.js","../src/LocalStreamManager.ts"],"names":["__assign","Object","assign","t","s","i","n","arguments","length","p","prototype","hasOwnProperty","call","apply","__importDefault","mod","__esModule","defineProperty","exports","value","LocalStreamManager","assign_1","require","get_1","last_1","first_1","cloneDeep_1","bluebird_1","MediaConstants_1","MediaTracer_1","window","latestUserMediaStream","userMediaPromise","latestDesktopMediaStream","desktopMediaPromise","mediaStreamAlreadyReplaced","latestLocalMediaConstraints","trace","getMediaTracer","environment","_groupedDevices","video","audio","camerasCount","parseMediaErrorThenThrow","bind","clearAllStreams","get","enumerable","configurable","getUserMediaStream","constraints","_this","info","videoTrack","mediaStream","getVideoTracks","readyState","Promise","resolve","isNew","destroyUserMediaStream","reject","catchHandler","err","error","getHighestResolutionStream","then","streamResult","constraint","getDesktopMediaStream","track","destroyDesktopMediaStream","mediaCatchHandler","getTracks","forEach","stop","e","all","undefined","isDesktopMedia","constraintsCandidates","getParsedConstraints","Error","lastSuccessfulResult","lastFailedResult","isStreamRequestFulfilled","reduce","total","candidate","constraintType","getStreamPromiseByParsedConstraints","stream","failResult","errorCode","MediaRequestErrorCode","PermissionDenied","GeneralError","message","getUserMediaStreamMediaDevice","streamPromise","navigator","mediaDevices","getUserMedia","getDisplayMedia","name","newConstraints","facingMode","deviceId","exact","setGroupedDevices","groupedDevices","_a","CameraTypes","BACK","FRONT","streamConstraints","constraintCandidates","baseConstraints","cameraType","videoSourceType","LocalVideoSourceType","CAMERA_FRONT","frameRate","ideal","max","assignConstraint","videoResolution","resolution","split","width","height","constraintCandidate","_constraintByType","push","Array","defaultResolution","DEFAULT_VIDEO_RESOLUTION","DEFAULT_VIDEO_CONSTRAINT_TYPE","errorName","permissionErrorNames","constraintsErrors","isErrorOfType","errorsArr","filter","Overconstrained","type","ConstraintType","MIN","min"],"mappings":"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","file":"LocalStreamManager.js","sourcesContent":["\"use strict\";\nvar __assign = (this && this.__assign) || function () {\n __assign = Object.assign || function(t) {\n for (var s, i = 1, n = arguments.length; i < n; i++) {\n s = arguments[i];\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))\n t[p] = s[p];\n }\n return t;\n };\n return __assign.apply(this, arguments);\n};\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.LocalStreamManager = void 0;\nvar assign_1 = __importDefault(require(\"lodash/assign\"));\nvar get_1 = __importDefault(require(\"lodash/get\"));\nvar last_1 = __importDefault(require(\"lodash/last\"));\nvar first_1 = __importDefault(require(\"lodash/first\"));\nvar cloneDeep_1 = __importDefault(require(\"lodash/cloneDeep\"));\nvar bluebird_1 = require(\"bluebird\");\nvar MediaConstants_1 = require(\"./MediaConstants\");\nvar MediaTracer_1 = require(\"./MediaUtils/MediaTracer\");\nwindow.latestUserMediaStream = null;\nvar userMediaPromise = null;\nwindow.latestDesktopMediaStream = null;\nvar desktopMediaPromise = null;\nwindow.mediaStreamAlreadyReplaced = false;\nwindow.latestLocalMediaConstraints = null;\nvar trace = MediaTracer_1.getMediaTracer('LocalStreamManager');\nvar LocalStreamManager = /** @class */ (function () {\n function LocalStreamManager(environment) {\n this._groupedDevices = { video: null, audio: null, camerasCount: 0 };\n this.environment = environment;\n this.parseMediaErrorThenThrow = this.parseMediaErrorThenThrow.bind(this);\n this.clearAllStreams = this.clearAllStreams.bind(this);\n }\n Object.defineProperty(LocalStreamManager.prototype, \"groupedDevices\", {\n get: function () {\n return this._groupedDevices;\n },\n enumerable: false,\n configurable: true\n });\n LocalStreamManager.prototype.getUserMediaStream = function (constraints) {\n var _this = this;\n trace.info('getUserMediaStream', constraints);\n if (userMediaPromise) {\n return userMediaPromise;\n }\n if (window.latestUserMediaStream) {\n var videoTrack = window.latestUserMediaStream.mediaStream.getVideoTracks();\n if (videoTrack.length > 0 && videoTrack[0].readyState === 'live') {\n return bluebird_1.Promise.resolve(__assign(__assign({}, window.latestUserMediaStream), { isNew: false }));\n }\n this.destroyUserMediaStream();\n }\n userMediaPromise = new bluebird_1.Promise(function (resolve, reject) {\n var catchHandler = function (err) {\n userMediaPromise = null;\n window.latestUserMediaStream = null;\n trace.error('getUserMedia error', err);\n reject(err);\n };\n try {\n _this.getHighestResolutionStream(false, constraints)\n .then(function (streamResult) {\n userMediaPromise = null;\n window.latestUserMediaStream = streamResult;\n window.latestLocalMediaConstraints = cloneDeep_1.default(constraints);\n window.latestLocalMediaConstraints.audio = (streamResult.constraint && streamResult.constraint.audio);\n resolve(__assign(__assign({}, window.latestUserMediaStream), { isNew: true }));\n })\n .catch(catchHandler);\n }\n catch (err) {\n catchHandler(err);\n }\n });\n return userMediaPromise;\n };\n LocalStreamManager.prototype.getDesktopMediaStream = function (constraints) {\n var _this = this;\n if (desktopMediaPromise) {\n return desktopMediaPromise;\n }\n trace.info('getDesktopMediaStream', constraints);\n if (window.latestDesktopMediaStream) {\n var track = window.latestDesktopMediaStream.mediaStream.getVideoTracks();\n if (track.length > 0 && track[0].readyState === 'live') {\n //return Promise.resolve();\n return bluebird_1.Promise.resolve(__assign(__assign({}, window.latestDesktopMediaStream), { isNew: false }));\n }\n this.destroyDesktopMediaStream().catch(function (error) {\n trace.error('Error destroying desktop media stream', error);\n });\n }\n desktopMediaPromise = new bluebird_1.Promise(function (resolve, reject) {\n var mediaCatchHandler = function (err) {\n desktopMediaPromise = null;\n window.latestDesktopMediaStream = null;\n trace.error('getDisplayMedia error', err);\n reject(err);\n };\n try {\n _this.getHighestResolutionStream(true, { video: constraints, audio: false })\n .then(function (streamResult) {\n desktopMediaPromise = null;\n window.latestDesktopMediaStream = streamResult;\n resolve(__assign(__assign({}, window.latestDesktopMediaStream), { isNew: true }));\n }).catch(mediaCatchHandler);\n }\n catch (err) {\n mediaCatchHandler(err);\n }\n });\n return desktopMediaPromise;\n };\n LocalStreamManager.prototype.destroyUserMediaStream = function () {\n var streamResult = window.latestUserMediaStream;\n userMediaPromise = null;\n window.latestUserMediaStream = null;\n window.latestLocalMediaConstraints = null;\n window.mediaStreamAlreadyReplaced = false;\n if (streamResult && streamResult.mediaStream) {\n try {\n streamResult.mediaStream.getTracks().forEach(function (track) {\n track.stop();\n });\n trace.info('destroyUserMediaStream - stop all tracks');\n }\n catch (e) {\n trace.info('destroyUserMediaStream - Failed to stop all tracks', e);\n }\n }\n return bluebird_1.Promise.resolve();\n };\n LocalStreamManager.prototype.destroyDesktopMediaStream = function () {\n var streamResult = window.latestDesktopMediaStream;\n window.latestDesktopMediaStream = null;\n desktopMediaPromise = null;\n if (streamResult && streamResult.mediaStream) {\n try {\n streamResult.mediaStream.getTracks().forEach(function (track) {\n track.stop();\n });\n trace.info('destroyDesktopMediaStream - stop all tracks');\n }\n catch (e) {\n trace.info('destroyDesktopMediaStream - Failed to stop all tracks', e);\n }\n }\n return bluebird_1.Promise.resolve();\n };\n LocalStreamManager.prototype.clearAllStreams = function () {\n trace.info('LocalStreamManager Clearing all streams');\n return bluebird_1.Promise.all([\n this.destroyDesktopMediaStream(),\n this.destroyUserMediaStream()\n ]).then(function () { return undefined; });\n };\n LocalStreamManager.prototype.getHighestResolutionStream = function (isDesktopMedia, constraints) {\n var _this = this;\n var constraintsCandidates = this.getParsedConstraints(isDesktopMedia, constraints);\n trace.info('getHighestResolutionStream - constraintsCandidates:', constraintsCandidates);\n if (constraintsCandidates.length === 0) {\n return bluebird_1.Promise.reject(new Error('No constraints to retrieve the stream'));\n }\n return new bluebird_1.Promise(function (resolve, reject) {\n var lastSuccessfulResult = null;\n var lastFailedResult = null;\n var isStreamRequestFulfilled = false;\n bluebird_1.Promise.reduce(constraintsCandidates, function (total, candidate) {\n if (isStreamRequestFulfilled) {\n return;\n }\n var constraintType = get_1.default(constraints, 'video.videoResolution.constraintType') || get_1.default(constraints, 'video.videoResolution[0].constraintType');\n return _this.getStreamPromiseByParsedConstraints(candidate, isDesktopMedia)\n .then(function (stream) {\n lastSuccessfulResult = {\n mediaStream: stream,\n constraint: candidate,\n constraintType: constraintType,\n isNew: true\n };\n trace.info('getHighestResolutionStream Success', lastSuccessfulResult);\n isStreamRequestFulfilled = true;\n resolve(lastSuccessfulResult);\n })\n .catch(function (failResult) {\n lastFailedResult = failResult;\n if (lastFailedResult.errorCode === MediaConstants_1.MediaRequestErrorCode.PermissionDenied) {\n isStreamRequestFulfilled = true;\n reject(lastFailedResult);\n }\n });\n }, 0)\n .then(function () {\n if (!isStreamRequestFulfilled) {\n if (!lastFailedResult) {\n lastFailedResult = {\n errorCode: MediaConstants_1.MediaRequestErrorCode.GeneralError,\n message: 'Suitable stream cannot be created'\n };\n }\n reject(lastFailedResult);\n }\n });\n });\n };\n LocalStreamManager.prototype.getUserMediaStreamMediaDevice = function (constraints, isDesktopMedia) {\n var streamPromise = null;\n if (!isDesktopMedia) {\n streamPromise = navigator.mediaDevices.getUserMedia(constraints);\n }\n else {\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n //@ts-ignore\n streamPromise = navigator.mediaDevices.getDisplayMedia\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n //@ts-ignore\n ? navigator.mediaDevices.getDisplayMedia(constraints)\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n //@ts-ignore\n : navigator.getDisplayMedia(constraints);\n }\n return streamPromise;\n };\n // eslint-disable-next-line consistent-return,@typescript-eslint/ban-ts-comment\n // @ts-ignore\n LocalStreamManager.prototype.getStreamPromiseByParsedConstraints = function (constraints, isDesktopMedia) {\n var _this = this;\n trace.info('getStreamPromiseByParsedConstraints', constraints);\n try {\n return this.getUserMediaStreamMediaDevice(constraints, isDesktopMedia).catch(function (err) {\n var streamPromise = null;\n trace.info('getStreamPromiseByParsedConstraints - get user stream error', err.name);\n // Android (Galaxy esp.) have a bug that when using facingMode it might cause NotReadableError. So\n // we should try again but without facingMode. The exception to the rule is when we don't have specific\n // device to use (like in IOS13 bug, as can be seen in MediaServiceBase.ts), in that case, we might end\n // up using the front camera, which is a privacy concern and the preference is to fallback from video\n if (err && (err.name === 'NotReadableError') && get_1.default(constraints, 'video.facingMode') &&\n get_1.default(constraints, 'video.deviceId')) {\n var newConstraints = constraints;\n trace.info(\"getStreamPromiseByParsedConstraints - NotReadableError - Failed to get video user media stream with facingMode=\" + get_1.default(constraints, 'video.facingMode'), err.name);\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n delete newConstraints.video.facingMode;\n newConstraints.video.deviceId = {\n exact: constraints.video.deviceId\n };\n streamPromise = _this.getStreamPromiseByParsedConstraints(newConstraints, isDesktopMedia);\n }\n else if (err && err.name && constraints.audio && !constraints.video) {\n trace.info('getStreamPromiseByParsedConstraints - audioStreamFailed - Failed to get audio user media stream', err.name);\n return _this.parseMediaErrorThenThrow({ name: 'audioStreamFailed' });\n }\n else if (err && err.name && constraints.audio) {\n var newConstraints = constraints;\n trace.info('getStreamPromiseByParsedConstraints - Failed to get video and audio user media stream, try to get video media stream only', err.name);\n newConstraints.audio = false;\n streamPromise = _this.getStreamPromiseByParsedConstraints(newConstraints, isDesktopMedia);\n }\n else if (err && !streamPromise) {\n trace.info('getStreamPromiseByParsedConstraints - Failed to get video user media stream', err && err.name);\n streamPromise = bluebird_1.Promise.reject(err);\n }\n return streamPromise && streamPromise.catch(_this.parseMediaErrorThenThrow);\n });\n }\n catch (e) {\n this.parseMediaErrorThenThrow(e);\n }\n };\n LocalStreamManager.prototype.setGroupedDevices = function (groupedDevices) {\n var _a;\n trace.info('setGroupedDevices', groupedDevices);\n this._groupedDevices = { video: groupedDevices.video\n ? (_a = {}, _a[MediaConstants_1.CameraTypes.BACK] = last_1.default(groupedDevices.video), _a[MediaConstants_1.CameraTypes.FRONT] = first_1.default(groupedDevices.video), _a) : null, audio: last_1.default(groupedDevices.audio) || null,\n camerasCount: groupedDevices.video.length };\n };\n LocalStreamManager.prototype.getParsedConstraints = function (isDesktopMedia, streamConstraints) {\n var constraintCandidates = [];\n //TODO - Alex: need to understand which constraints not compatible with screen share\n if (isDesktopMedia) {\n return [{ video: true }];\n }\n if (!streamConstraints) {\n return constraintCandidates;\n }\n var baseConstraints = {};\n baseConstraints.audio = typeof streamConstraints.audio === 'boolean' ? streamConstraints.audio : undefined;\n if (!streamConstraints.video) {\n return [baseConstraints];\n }\n var cameraType = (streamConstraints.video !== 'boolean') &&\n streamConstraints.video.videoSourceType;\n baseConstraints.video = {\n facingMode: cameraType && cameraType === MediaConstants_1.LocalVideoSourceType.CAMERA_FRONT\n ? 'user'\n : 'environment',\n frameRate: { ideal: 15, max: 30 }\n };\n var deviceId = get_1.default(this._groupedDevices, \"video.\" + (cameraType === MediaConstants_1.LocalVideoSourceType.CAMERA_FRONT\n ? MediaConstants_1.CameraTypes.FRONT\n : MediaConstants_1.CameraTypes.BACK) + \".deviceId\");\n if (deviceId) {\n baseConstraints.video.deviceId = deviceId;\n if (this._groupedDevices.camerasCount > 1) {\n baseConstraints.video.facingMode = { exact: baseConstraints.video.facingMode };\n }\n }\n var assignConstraint = function (videoResolution) {\n var _a = videoResolution.resolution.split('x'), width = _a[0], height = _a[1];\n var constraintCandidate = assign_1.default({}, baseConstraints);\n constraintCandidate.video = assign_1.default({}, baseConstraints.video, {\n width: _constraintByType(width, videoResolution.constraintType),\n height: _constraintByType(height, videoResolution.constraintType)\n });\n constraintCandidates.push(constraintCandidate);\n };\n if ((baseConstraints.video && typeof streamConstraints.video === 'boolean') ||\n !(streamConstraints.video.videoResolution instanceof Array)) {\n var defaultResolution = {\n resolution: MediaConstants_1.DEFAULT_VIDEO_RESOLUTION,\n constraintType: MediaConstants_1.DEFAULT_VIDEO_CONSTRAINT_TYPE\n };\n assignConstraint(defaultResolution);\n return constraintCandidates;\n }\n streamConstraints.video.videoResolution.forEach(assignConstraint);\n return constraintCandidates;\n };\n LocalStreamManager.prototype.parseMediaErrorThenThrow = function (error) {\n if (error && error.errorCode) {\n throw error;\n }\n trace.error('Get media stream error.', error);\n var errorName = error && error.name ? error.name : '';\n var permissionErrorNames = [\n 'NotAllowedError',\n 'PermissionDismissedError',\n 'PermissionDeniedError'\n ];\n // const generalError = [\n // 'NotFoundError',\n // 'DevicesNotFoundError',\n // 'NotReadableError',\n // 'TrackStartError'\n // ];\n var constraintsErrors = [\n 'OverconstrainedError',\n 'ConstraintNotSatisfiedError'\n ];\n var isErrorOfType = function (errorsArr) { return errorsArr.filter(function (err) { return err === errorName; }).length > 0; };\n if (isErrorOfType(permissionErrorNames)) {\n throw { errorCode: MediaConstants_1.MediaRequestErrorCode.PermissionDenied, message: errorName };\n }\n if (isErrorOfType(constraintsErrors)) {\n throw { errorCode: MediaConstants_1.MediaRequestErrorCode.Overconstrained, message: errorName };\n }\n throw { errorCode: MediaConstants_1.MediaRequestErrorCode.GeneralError, message: errorName };\n };\n return LocalStreamManager;\n}());\nexports.LocalStreamManager = LocalStreamManager;\nfunction _constraintByType(value, type) {\n switch (type) {\n case MediaConstants_1.ConstraintType.MIN:\n return { min: value };\n default:\n return { ideal: value };\n }\n}\n\n//# sourceMappingURL=LocalStreamManager.js.map\n","import assign from 'lodash/assign';\nimport get from 'lodash/get';\nimport last from 'lodash/last';\nimport first from 'lodash/first';\nimport cloneDeep from 'lodash/cloneDeep';\nimport {Promise} from 'bluebird';\n\nimport {Nullable} from '@techsee/techsee-common';\n\nimport {\n IMediaEnvironment,\n LocalMediaConstraints,\n LocalVideoStreamConstraints,\n MediaRequestFailResult,\n MediaRequestSuccessResult,\n VideoStreamResolution\n} from './MediaContracts';\n\nimport {\n CameraTypes,\n ConstraintType,\n DEFAULT_VIDEO_CONSTRAINT_TYPE,\n DEFAULT_VIDEO_RESOLUTION,\n LocalVideoSourceType,\n MediaRequestErrorCode\n} from './MediaConstants';\nimport {getMediaTracer} from './MediaUtils/MediaTracer';\n\ndeclare global {\n interface Window {\n latestUserMediaStream: Nullable<MediaRequestSuccessResult>;\n latestDesktopMediaStream: Nullable<MediaRequestSuccessResult>;\n latestLocalMediaConstraints: Nullable<LocalMediaConstraints>;\n mediaStreamAlreadyReplaced: boolean;\n }\n}\n\ndeclare const window: Window;\n\nwindow.latestUserMediaStream = null;\nlet userMediaPromise: Nullable<Promise<MediaRequestSuccessResult>> = null;\n\nwindow.latestDesktopMediaStream = null;\nlet desktopMediaPromise: Nullable<Promise<MediaRequestSuccessResult>> = null;\n\nwindow.mediaStreamAlreadyReplaced = false;\nwindow.latestLocalMediaConstraints = null;\n\nconst trace = getMediaTracer('LocalStreamManager');\n\ninterface IGroupedDevices {\n video: Nullable<{ back?: MediaDeviceInfo; front?: MediaDeviceInfo }>;\n audio: Nullable<MediaDeviceInfo>;\n camerasCount: number;\n}\n\nexport class LocalStreamManager {\n private environment: IMediaEnvironment;\n private _groupedDevices: IGroupedDevices = {video: null, audio: null, camerasCount: 0};\n\n constructor(environment: IMediaEnvironment) {\n this.environment = environment;\n\n this.parseMediaErrorThenThrow = this.parseMediaErrorThenThrow.bind(this);\n this.clearAllStreams = this.clearAllStreams.bind(this);\n }\n\n get groupedDevices() {\n return this._groupedDevices;\n }\n\n getUserMediaStream(constraints: LocalMediaConstraints): Promise<MediaRequestSuccessResult> {\n trace.info('getUserMediaStream', constraints);\n if (userMediaPromise) {\n return userMediaPromise;\n }\n\n if (window.latestUserMediaStream) {\n const videoTrack = window.latestUserMediaStream.mediaStream.getVideoTracks();\n\n if (videoTrack.length > 0 && videoTrack[0].readyState === 'live') {\n return Promise.resolve({...window.latestUserMediaStream, isNew: false});\n }\n\n this.destroyUserMediaStream();\n }\n\n userMediaPromise = new Promise((resolve, reject) => {\n const catchHandler = (err: any): void => {\n userMediaPromise = null;\n window.latestUserMediaStream = null;\n trace.error('getUserMedia error', err);\n reject(err);\n };\n\n try {\n this.getHighestResolutionStream(false, constraints)\n .then((streamResult: MediaRequestSuccessResult) => {\n userMediaPromise = null;\n window.latestUserMediaStream = streamResult;\n window.latestLocalMediaConstraints = cloneDeep(constraints);\n window.latestLocalMediaConstraints.audio = (streamResult.constraint && streamResult.constraint.audio) as boolean;\n\n resolve({...window.latestUserMediaStream, isNew: true});\n })\n .catch(catchHandler);\n } catch (err) {\n catchHandler(err);\n }\n });\n\n return userMediaPromise;\n }\n\n getDesktopMediaStream(constraints: LocalVideoStreamConstraints): Promise<MediaRequestSuccessResult> {\n if (desktopMediaPromise) {\n return desktopMediaPromise;\n }\n\n trace.info('getDesktopMediaStream', constraints);\n\n if (window.latestDesktopMediaStream) {\n const track = window.latestDesktopMediaStream.mediaStream.getVideoTracks();\n\n if (track.length > 0 && track[0].readyState === 'live') {\n //return Promise.resolve();\n return Promise.resolve({...window.latestDesktopMediaStream, isNew: false});\n }\n this.destroyDesktopMediaStream().catch((error: any) => {\n trace.error('Error destroying desktop media stream', error);\n });\n\n }\n\n desktopMediaPromise = new Promise((resolve, reject) => {\n const mediaCatchHandler = (err: any): void => {\n desktopMediaPromise = null;\n window.latestDesktopMediaStream = null;\n trace.error('getDisplayMedia error', err);\n reject(err);\n };\n\n try {\n this.getHighestResolutionStream(true, {video: constraints, audio: false})\n .then((streamResult: MediaRequestSuccessResult) => {\n desktopMediaPromise = null;\n window.latestDesktopMediaStream = streamResult;\n\n resolve({...window.latestDesktopMediaStream, isNew: true});\n }).catch(mediaCatchHandler);\n } catch (err) {\n mediaCatchHandler(err);\n }\n });\n\n return desktopMediaPromise;\n }\n\n destroyUserMediaStream(): Promise<void> {\n const streamResult = window.latestUserMediaStream;\n\n userMediaPromise = null;\n window.latestUserMediaStream = null;\n window.latestLocalMediaConstraints = null;\n window.mediaStreamAlreadyReplaced = false;\n\n if (streamResult && streamResult.mediaStream) {\n try {\n streamResult.mediaStream.getTracks().forEach((track: MediaStreamTrack) => {\n track.stop();\n });\n\n trace.info('destroyUserMediaStream - stop all tracks');\n } catch (e) {\n trace.info('destroyUserMediaStream - Failed to stop all tracks', e);\n }\n }\n\n return Promise.resolve();\n }\n\n destroyDesktopMediaStream(): Promise<void> {\n const streamResult = window.latestDesktopMediaStream;\n\n window.latestDesktopMediaStream = null;\n desktopMediaPromise = null;\n\n if (streamResult && streamResult.mediaStream) {\n try {\n streamResult.mediaStream.getTracks().forEach((track: MediaStreamTrack) => {\n track.stop();\n });\n\n trace.info('destroyDesktopMediaStream - stop all tracks');\n } catch (e) {\n trace.info('destroyDesktopMediaStream - Failed to stop all tracks', e);\n }\n }\n\n return Promise.resolve();\n }\n\n clearAllStreams(): Promise<void> {\n trace.info('LocalStreamManager Clearing all streams');\n\n return Promise.all([\n this.destroyDesktopMediaStream(),\n this.destroyUserMediaStream()\n ]).then(() => undefined);\n }\n\n private getHighestResolutionStream(isDesktopMedia: boolean, constraints?: LocalMediaConstraints): Promise<MediaRequestSuccessResult> {\n const constraintsCandidates = this.getParsedConstraints(isDesktopMedia, constraints);\n\n trace.info('getHighestResolutionStream - constraintsCandidates:', constraintsCandidates);\n\n if (constraintsCandidates.length === 0) {\n return Promise.reject(new Error('No constraints to retrieve the stream'));\n }\n\n return new Promise((resolve, reject) => {\n let lastSuccessfulResult: Nullable<MediaRequestSuccessResult> = null;\n let lastFailedResult: Nullable<MediaRequestFailResult> = null;\n let isStreamRequestFulfilled = false;\n\n (Promise as any).reduce(constraintsCandidates, (total: any, candidate: MediaStreamConstraints) => {\n if (isStreamRequestFulfilled) {\n return;\n }\n\n const constraintType = get(constraints, 'video.videoResolution.constraintType') || get(constraints, 'video.videoResolution[0].constraintType');\n\n return this.getStreamPromiseByParsedConstraints(candidate, isDesktopMedia)\n .then((stream: MediaStream) => {\n lastSuccessfulResult = {\n mediaStream: stream,\n constraint: candidate,\n constraintType,\n isNew: true\n };\n trace.info('getHighestResolutionStream Success', lastSuccessfulResult);\n isStreamRequestFulfilled = true;\n resolve(lastSuccessfulResult);\n })\n .catch((failResult: MediaRequestFailResult) => {\n lastFailedResult = failResult;\n\n if (lastFailedResult.errorCode === MediaRequestErrorCode.PermissionDenied) {\n isStreamRequestFulfilled = true;\n reject(lastFailedResult);\n }\n });\n }, 0)\n .then(() => {\n if (!isStreamRequestFulfilled) {\n if (!lastFailedResult) {\n lastFailedResult = {\n errorCode: MediaRequestErrorCode.GeneralError,\n message: 'Suitable stream cannot be created'\n };\n }\n reject(lastFailedResult);\n }\n });\n });\n }\n\n private getUserMediaStreamMediaDevice(constraints: MediaStreamConstraints, isDesktopMedia: boolean) {\n let streamPromise = null;\n\n if (!isDesktopMedia) {\n streamPromise = navigator.mediaDevices.getUserMedia(constraints);\n } else {\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n //@ts-ignore\n streamPromise = navigator.mediaDevices.getDisplayMedia\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n //@ts-ignore\n ? navigator.mediaDevices.getDisplayMedia(constraints)\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n //@ts-ignore\n : navigator.getDisplayMedia(constraints);\n }\n\n return streamPromise;\n }\n\n // eslint-disable-next-line consistent-return,@typescript-eslint/ban-ts-comment\n // @ts-ignore\n private getStreamPromiseByParsedConstraints(constraints: MediaStreamConstraints, isDesktopMedia: boolean): Promise<MediaStream> {\n trace.info('getStreamPromiseByParsedConstraints', constraints);\n\n try {\n return this.getUserMediaStreamMediaDevice(constraints, isDesktopMedia).catch((err: any) => {\n let streamPromise = null;\n\n trace.info('getStreamPromiseByParsedConstraints - get user stream error', err.name);\n\n // Android (Galaxy esp.) have a bug that when using facingMode it might cause NotReadableError. So\n // we should try again but without facingMode. The exception to the rule is when we don't have specific\n // device to use (like in IOS13 bug, as can be seen in MediaServiceBase.ts), in that case, we might end\n // up using the front camera, which is a privacy concern and the preference is to fallback from video\n if (err && (err.name === 'NotReadableError') && get(constraints, 'video.facingMode') &&\n get(constraints, 'video.deviceId')) {\n\n const newConstraints = constraints;\n\n trace.info(`getStreamPromiseByParsedConstraints - NotReadableError - Failed to get video user media stream with facingMode=${get(constraints, 'video.facingMode')}`, err.name);\n\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n delete newConstraints.video.facingMode;\n ((newConstraints.video as MediaTrackConstraints).deviceId as ConstrainDOMStringParameters) = {\n exact: (constraints.video as MediaTrackConstraints).deviceId\n } as any as ConstrainDOMStringParameters;\n\n streamPromise = this.getStreamPromiseByParsedConstraints(newConstraints, isDesktopMedia);\n } else if (err && err.name && constraints.audio && !constraints.video) {\n trace.info('getStreamPromiseByParsedConstraints - audioStreamFailed - Failed to get audio user media stream', err.name);\n\n return this.parseMediaErrorThenThrow({name: 'audioStreamFailed'});\n } else if (err && err.name && constraints.audio) {\n const newConstraints = constraints;\n\n trace.info('getStreamPromiseByParsedConstraints - Failed to get video and audio user media stream, try to get video media stream only', err.name);\n\n newConstraints.audio = false;\n streamPromise = this.getStreamPromiseByParsedConstraints(newConstraints, isDesktopMedia);\n } else if (err && !streamPromise) {\n trace.info('getStreamPromiseByParsedConstraints - Failed to get video user media stream', err && err.name);\n\n streamPromise = Promise.reject(err);\n }\n\n return streamPromise && streamPromise.catch(this.parseMediaErrorThenThrow);\n });\n } catch (e) {\n this.parseMediaErrorThenThrow(e);\n }\n }\n\n setGroupedDevices(groupedDevices: {video: MediaDeviceInfo[]; audio: MediaDeviceInfo[]}) {\n trace.info('setGroupedDevices', groupedDevices);\n this._groupedDevices = {video: groupedDevices.video\n ? {[CameraTypes.BACK]: last(groupedDevices.video), [CameraTypes.FRONT]: first(groupedDevices.video)}\n : null,\n audio: last(groupedDevices.audio) || null,\n camerasCount: groupedDevices.video.length};\n }\n\n private getParsedConstraints(isDesktopMedia: boolean, streamConstraints?: LocalMediaConstraints): MediaStreamConstraints[] {\n const constraintCandidates: MediaStreamConstraints[] = [];\n\n //TODO - Alex: need to understand which constraints not compatible with screen share\n if (isDesktopMedia) {\n return [{video: true}];\n }\n\n if (!streamConstraints) {\n return constraintCandidates;\n }\n\n const baseConstraints: MediaStreamConstraints = {};\n\n baseConstraints.audio = typeof streamConstraints.audio === 'boolean' ? streamConstraints.audio : undefined;\n\n if (!streamConstraints.video) {\n return [baseConstraints];\n }\n\n const cameraType = (streamConstraints.video !== 'boolean') &&\n (streamConstraints.video as LocalVideoStreamConstraints).videoSourceType;\n\n baseConstraints.video = {\n facingMode: cameraType && cameraType === LocalVideoSourceType.CAMERA_FRONT\n ? 'user'\n : 'environment',\n frameRate: {ideal: 15, max: 30}\n };\n\n const deviceId = get(this._groupedDevices, `video.${cameraType === LocalVideoSourceType.CAMERA_FRONT\n ? CameraTypes.FRONT\n : CameraTypes.BACK}.deviceId`);\n\n if (deviceId) {\n baseConstraints.video.deviceId = deviceId;\n\n if (this._groupedDevices.camerasCount > 1) {\n baseConstraints.video.facingMode = {exact: baseConstraints.video.facingMode} as any as ConstrainDOMStringParameters;\n }\n }\n\n const assignConstraint = (videoResolution: VideoStreamResolution): void => {\n const [width, height] = videoResolution.resolution.split('x');\n const constraintCandidate = assign({}, baseConstraints);\n\n constraintCandidate.video = assign({}, baseConstraints.video, {\n width: _constraintByType(width, videoResolution.constraintType),\n height: _constraintByType(height, videoResolution.constraintType)\n });\n constraintCandidates.push(constraintCandidate);\n };\n\n if ((baseConstraints.video && typeof streamConstraints.video === 'boolean') ||\n !((streamConstraints.video as LocalVideoStreamConstraints).videoResolution instanceof Array)) {\n\n const defaultResolution: VideoStreamResolution = {\n resolution: DEFAULT_VIDEO_RESOLUTION,\n constraintType: DEFAULT_VIDEO_CONSTRAINT_TYPE\n };\n\n assignConstraint(defaultResolution);\n\n return constraintCandidates;\n }\n\n (streamConstraints.video as any).videoResolution.forEach(assignConstraint);\n\n return constraintCandidates;\n }\n\n private parseMediaErrorThenThrow(error: any): MediaRequestFailResult {\n if (error && error.errorCode) {\n throw error;\n }\n\n trace.error('Get media stream error.', error);\n const errorName = error && error.name ? error.name : '';\n\n const permissionErrorNames = [\n 'NotAllowedError',\n 'PermissionDismissedError',\n 'PermissionDeniedError'\n\n ];\n\n // const generalError = [\n // 'NotFoundError',\n // 'DevicesNotFoundError',\n // 'NotReadableError',\n // 'TrackStartError'\n // ];\n\n const constraintsErrors = [\n 'OverconstrainedError',\n 'ConstraintNotSatisfiedError'\n\n ];\n\n const isErrorOfType = (errorsArr: string[]) => errorsArr.filter((err: string) => err === errorName).length > 0;\n\n if (isErrorOfType(permissionErrorNames)) {\n throw {errorCode: MediaRequestErrorCode.PermissionDenied, message: errorName};\n }\n\n if (isErrorOfType(constraintsErrors)) {\n throw {errorCode: MediaRequestErrorCode.Overconstrained, message: errorName};\n }\n\n throw {errorCode: MediaRequestErrorCode.GeneralError, message: errorName};\n }\n}\n\nfunction _constraintByType(value: any, type: ConstraintType): any {\n switch (type) {\n case ConstraintType.MIN:\n return {min: value};\n default:\n return {ideal: value};\n }\n}\n"]}
|
package/lib/MediaConstants.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { VideoStreamResolution } from './MediaContracts';
|
|
2
|
-
import { CameraTypes } from '@techsee/techsee-common/lib/constants/media.constants';
|
|
3
2
|
export declare enum LocalVideoSourceType {
|
|
4
3
|
CAMERA = "CAMERA",
|
|
5
4
|
CAMERA_FRONT = "CAMERA_FRONT",
|
|
@@ -9,14 +8,10 @@ export declare enum ConstraintType {
|
|
|
9
8
|
MIN = "min",
|
|
10
9
|
IDEAL = "ideal"
|
|
11
10
|
}
|
|
12
|
-
export declare enum
|
|
13
|
-
CAMERA = "camera",
|
|
14
|
-
SCREEN = "screen",
|
|
15
|
-
NOTHING = ""
|
|
16
|
-
}
|
|
17
|
-
export declare enum MultiPartyCameraTypes {
|
|
11
|
+
export declare enum CameraTypes {
|
|
18
12
|
FRONT = "front",
|
|
19
|
-
BACK = "back"
|
|
13
|
+
BACK = "back",
|
|
14
|
+
NONE = "none"
|
|
20
15
|
}
|
|
21
16
|
export declare enum MediaServiceType {
|
|
22
17
|
OPENTOK = "OPENTOK",
|
|
@@ -63,20 +58,9 @@ export declare enum MediaStreamUnregisterReason {
|
|
|
63
58
|
ClosedRemotely = "ClosedRemotely",
|
|
64
59
|
ServiceCleanUp = "ServiceCleanUp"
|
|
65
60
|
}
|
|
66
|
-
export declare enum VideoResolutionMultiplication {
|
|
67
|
-
HD = 829440,
|
|
68
|
-
SD = 230400
|
|
69
|
-
}
|
|
70
|
-
export declare enum VideoResolutionFormat {
|
|
71
|
-
HD = "HD",
|
|
72
|
-
SD = "SD",
|
|
73
|
-
NONE = "none"
|
|
74
|
-
}
|
|
75
61
|
export declare const DEFAULT_VIDEO_RESOLUTION = "640x480";
|
|
76
62
|
export declare const DEFAULT_VIDEO_CONSTRAINT_TYPE = ConstraintType.IDEAL;
|
|
77
63
|
export declare const DEFAULT_PEER_CONNECTIVITY_TIMEOUT_SECONDS = 10;
|
|
78
64
|
export declare const DEFAULT_VIDEO_WAIT_TIMEOUT_SECONDS = 30;
|
|
79
65
|
export declare const DEFAULT_VIDEO_CONSTRAINTS: VideoStreamResolution;
|
|
80
66
|
export declare const POSSIBLE_LOOPBACK_RESOLUTIONS: VideoStreamResolution[];
|
|
81
|
-
export declare const HD_RESOLUTION = "1280x720";
|
|
82
|
-
export { CameraTypes };
|