@antmedia/web_player 2.8.2 → 2.8.3-SNAPSHOT-2024-Feb-12-05-20
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/.github/workflows/publish-snapshot.yml +2 -1
- package/README.md +47 -35
- package/dist/browser/web_player.js +36 -6
- package/dist/es/index.d.ts +6 -2
- package/dist/es/web_player.js +36 -6
- package/dist/index.d.ts +9 -3
- package/dist/web_player.js +36 -6
- package/package.json +1 -1
- package/src/web_player.js +49 -12
- package/test/embedded-player.test.js +113 -6
- package/.project +0 -17
- package/.settings/.jsdtscope +0 -7
- package/.settings/org.eclipse.wst.jsdt.ui.superType.container +0 -1
- package/.settings/org.eclipse.wst.jsdt.ui.superType.name +0 -1
|
@@ -22,7 +22,8 @@ jobs:
|
|
|
22
22
|
- run: npm install --include=dev
|
|
23
23
|
- run: npm run compile
|
|
24
24
|
- run: npm test
|
|
25
|
-
|
|
25
|
+
#Fix this versioning for the snapshots
|
|
26
|
+
- run: npm version 2.8.3-SNAPSHOT"-`date +"%Y-%b-%d-%I-%M"`" --no-git-tag-version
|
|
26
27
|
- run: npm publish --tag SNAPSHOT
|
|
27
28
|
env:
|
|
28
29
|
NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}
|
package/README.md
CHANGED
|
@@ -20,59 +20,71 @@ Install the Web Player package using npm:
|
|
|
20
20
|
npm i @antmedia/web_player
|
|
21
21
|
```
|
|
22
22
|
|
|
23
|
-
## Configuration Parameters
|
|
24
|
-
|
|
25
|
-
The player accepts several configuration parameters, either through the URL or directly in the code:
|
|
26
|
-
|
|
27
|
-
1. `id` (String): The stream ID to play. This parameter is mandatory.
|
|
28
|
-
2. `token` (String): The token for stream access. It's mandatory if token security is enabled on the server side.
|
|
29
|
-
3. `autoplay` (Boolean): Autoplay the stream if available. Optional. Default value is `true`.
|
|
30
|
-
4. `mute` (Boolean): Start playing in mute mode if the stream is available. Optional. Default value is `true`.
|
|
31
|
-
5. `playOrder` (String): The order of technologies used for playing. Optional. Default value is `"webrtc,hls"`. Possible values include `"hls,webrtc"`, `"webrtc"`, `"hls"`, `"vod"`, `"dash"`.
|
|
32
|
-
6. `playType` (String): The order of play types used for playing. Optional. Default value is `"mp4,webm"`. Possible values include `"webm,mp4"`, `"mp4"`, `"webm"`, `"mov"`.
|
|
33
|
-
7. `targetLatency` (Number): The target latency for the DASH player. Optional. Default value is `3`.
|
|
34
|
-
8. `is360` (Boolean): Enable playback in 360 mode. Optional. Default value is `false`.
|
|
35
|
-
|
|
36
23
|
## Usage
|
|
37
24
|
|
|
38
25
|
### Basic Usage
|
|
39
26
|
|
|
40
|
-
|
|
27
|
+
To use the Web Player, import it and initialize it with the parameters received from the URL. Refer to the Configuration Parameters section below for more details.
|
|
41
28
|
|
|
42
|
-
|
|
43
|
-
import { WebPlayer } from "@antmedia/web_player";
|
|
29
|
+
1. In your web application, create a div with the id video_container. This will serve as the container for the player.
|
|
44
30
|
|
|
45
|
-
|
|
31
|
+
```
|
|
32
|
+
<div id="video_container" ></div>
|
|
33
|
+
````
|
|
34
|
+
|
|
35
|
+
2. Initialize the player as follows:
|
|
36
|
+
```javascript
|
|
37
|
+
import { WebPlayer } from "@antmedia/web_player";
|
|
46
38
|
|
|
47
|
-
embeddedPlayer
|
|
39
|
+
var embeddedPlayer = new WebPlayer(window, document.getElementById("video_container"), null);
|
|
40
|
+
|
|
41
|
+
embeddedPlayer.initialize().then(() => {
|
|
48
42
|
embeddedPlayer.play();
|
|
49
|
-
});
|
|
50
|
-
```
|
|
43
|
+
});
|
|
44
|
+
```
|
|
51
45
|
|
|
52
46
|
The sample for this usage is available in [play.html in StreamApp](https://github.com/ant-media/StreamApp/blob/master/src/main/webapp/play.html)
|
|
53
47
|
|
|
54
48
|
### Advanced Usage
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
49
|
+
Alternatively, you can pass the parameters as an object to the WebPlayer constructor.
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
1. In your web application, create a div with the id video_container. This will serve as the container for the player.
|
|
53
|
+
```
|
|
54
|
+
<div id="video_container" ></div>
|
|
55
|
+
````
|
|
56
|
+
|
|
57
|
+
2. Initialize the player as follows
|
|
58
|
+
```javascript
|
|
59
|
+
var player = new WebPlayer({
|
|
60
|
+
streamId: "myStreamId",
|
|
61
|
+
httpBaseURL: "http://example.antmedia.io:5080/WebRTCAppEE/", //Remember to add trailing slash(/)
|
|
62
|
+
}, document.getElementById("video_container"), null);
|
|
63
|
+
|
|
64
|
+
player.initialize().then(() => {
|
|
67
65
|
player.play();
|
|
68
|
-
}).catch((error) => {
|
|
66
|
+
}).catch((error) => {
|
|
69
67
|
console.error("Error while initializing embedded player: " + error);
|
|
70
|
-
});
|
|
71
|
-
```
|
|
68
|
+
});
|
|
69
|
+
```
|
|
72
70
|
|
|
73
71
|
The sample for this usage is available in [app.page.component.ts in Ant-Media-Management-Console](https://github.com/ant-media/Ant-Media-Management-Console/blob/master/src/app/app.page/app.page.component.ts)
|
|
74
72
|
|
|
75
73
|
|
|
74
|
+
## Configuration Parameters
|
|
75
|
+
|
|
76
|
+
The player accepts several configuration parameters, either through the URL or directly in the code:
|
|
77
|
+
|
|
78
|
+
1. `id` (String): The stream ID to play. This parameter is mandatory.
|
|
79
|
+
2. `token` (String): The token for stream access. It's mandatory if token security is enabled on the server side.
|
|
80
|
+
3. `autoplay` (Boolean): Autoplay the stream if available. Optional. Default value is `true`.
|
|
81
|
+
4. `mute` (Boolean): Start playing in mute mode if the stream is available. Optional. Default value is `true`.
|
|
82
|
+
5. `playOrder` (String): The order of technologies used for playing. Optional. Default value is `"webrtc,hls"`. Possible values include `"hls,webrtc"`, `"webrtc"`, `"hls"`, `"vod"`, `"dash"`.
|
|
83
|
+
6. `playType` (String): The order of play types used for playing. Optional. Default value is `"mp4,webm"`. Possible values include `"webm,mp4"`, `"mp4"`, `"webm"`, `"mov"`.
|
|
84
|
+
7. `targetLatency` (Number): The target latency for the DASH player. Optional. Default value is `3`.
|
|
85
|
+
8. `is360` (Boolean): Enable playback in 360 mode. Optional. Default value is `false`.
|
|
86
|
+
|
|
87
|
+
|
|
76
88
|
## Support
|
|
77
89
|
For support and further inquiries, please visit [Ant Media Server's community](https://github.com/orgs/ant-media/discussions). If you are an enterprise user, you can receive support by sending an email to support@antmedia.io.
|
|
78
90
|
|
|
@@ -112,11 +112,14 @@
|
|
|
112
112
|
*/
|
|
113
113
|
_defineProperty(this, "autoPlay", true);
|
|
114
114
|
/**
|
|
115
|
-
* mute: if
|
|
116
|
-
* default value is true because of browser's autoplay policy.
|
|
115
|
+
* mute: if false the player will try to auto play the stream with audio if it fails player will mute the audio and try again to autoplay it.
|
|
117
116
|
* It will be taken from url parameter "mute".
|
|
118
117
|
*/
|
|
119
|
-
_defineProperty(this, "mute",
|
|
118
|
+
_defineProperty(this, "mute", false);
|
|
119
|
+
/**
|
|
120
|
+
* Force the Player to play with audio Auto Play might not work.
|
|
121
|
+
*/
|
|
122
|
+
_defineProperty(this, "forcePlayWithAudio", false);
|
|
120
123
|
/**
|
|
121
124
|
* targetLatency: target latency in seconds. Optional. Default value is 3.
|
|
122
125
|
* It will be taken from url parameter "targetLatency".
|
|
@@ -293,7 +296,7 @@
|
|
|
293
296
|
this.playType = WebPlayer.DEFAULT_PLAY_TYPE;
|
|
294
297
|
this.token = null;
|
|
295
298
|
this.autoPlay = true;
|
|
296
|
-
this.mute =
|
|
299
|
+
this.mute = false;
|
|
297
300
|
this.targetLatency = 3;
|
|
298
301
|
this.subscriberId = null;
|
|
299
302
|
this.subscriberCode = null;
|
|
@@ -317,6 +320,7 @@
|
|
|
317
320
|
this.dashjsLoaded = false;
|
|
318
321
|
this.containerElementInitialDisplay = "block";
|
|
319
322
|
this.placeHolderElementInitialDisplay = "block";
|
|
323
|
+
this.forcePlayWithAudio = false;
|
|
320
324
|
}
|
|
321
325
|
initializeFromUrlParams() {
|
|
322
326
|
var _getUrlParameter;
|
|
@@ -342,7 +346,9 @@
|
|
|
342
346
|
var muteLocal = fetch_stream.getUrlParameter("mute", this.window.location.search);
|
|
343
347
|
if (muteLocal === "false") {
|
|
344
348
|
this.mute = false;
|
|
345
|
-
|
|
349
|
+
//user specifically asks to play with audio so if it fails in auto play, it will not try to play without audio
|
|
350
|
+
this.forcePlayWithAudio = true;
|
|
351
|
+
} else if (muteLocal === "true") {
|
|
346
352
|
this.mute = true;
|
|
347
353
|
}
|
|
348
354
|
var localTargetLatency = fetch_stream.getUrlParameter("targetLatency", this.window.location.search);
|
|
@@ -514,7 +520,7 @@
|
|
|
514
520
|
autoplay: this.autoPlay
|
|
515
521
|
});
|
|
516
522
|
this.videojsPlayer.on('error', e => {
|
|
517
|
-
loglevel_min.Logger.warn("There is an error in playback: "
|
|
523
|
+
loglevel_min.Logger.warn("There is an error in playback: ", e);
|
|
518
524
|
// We need to add this kind of check. If we don't add this kind of checkpoint, it will create an infinite loop
|
|
519
525
|
if (!this.errorCalled) {
|
|
520
526
|
this.errorCalled = true;
|
|
@@ -654,7 +660,16 @@
|
|
|
654
660
|
reconnect: false //webrtc adaptor has auto reconnect scenario, just disable it, we manage it here
|
|
655
661
|
});
|
|
656
662
|
if (this.autoPlay) {
|
|
663
|
+
//try to play directly
|
|
657
664
|
this.videojsPlayer.play().catch(e => {
|
|
665
|
+
//if it's not allowed error and default value are being used, try to play it muted
|
|
666
|
+
//if this.forcePlayWithAudio is true, it means user specifically ask to do.
|
|
667
|
+
// If it's false, it's default value so that we can proceed to try to play with muted
|
|
668
|
+
//This implementation is added because of auto play policy of the browsers
|
|
669
|
+
if (e.name === "NotAllowedError" && !this.forcePlayWithAudio) {
|
|
670
|
+
this.videojsPlayer.muted(true);
|
|
671
|
+
this.videojsPlayer.play();
|
|
672
|
+
}
|
|
658
673
|
loglevel_min.Logger.warn("Problem in playback. The error is " + e);
|
|
659
674
|
});
|
|
660
675
|
}
|
|
@@ -814,11 +829,26 @@
|
|
|
814
829
|
}
|
|
815
830
|
});
|
|
816
831
|
this.dashPlayer.on(dashjs.MediaPlayer.events.PLAYBACK_ERROR, event => {
|
|
832
|
+
loglevel_min.Logger.warn("dash playback error: " + event);
|
|
817
833
|
this.tryNextTech();
|
|
818
834
|
});
|
|
819
835
|
this.dashPlayer.on(dashjs.MediaPlayer.events.ERROR, event => {
|
|
836
|
+
loglevel_min.Logger.warn("error: " + event);
|
|
820
837
|
this.tryNextTech();
|
|
821
838
|
});
|
|
839
|
+
this.dashPlayer.on(dashjs.MediaPlayer.events.PLAYBACK_NOT_ALLOWED, event => {
|
|
840
|
+
loglevel_min.Logger.warn("dash playback not allowed: " + event);
|
|
841
|
+
this.handleDashPlayBackNotAllowed();
|
|
842
|
+
});
|
|
843
|
+
}
|
|
844
|
+
handleDashPlayBackNotAllowed() {
|
|
845
|
+
if (!this.forcePlayWithAudio) {
|
|
846
|
+
loglevel_min.Logger.info("Try to play with muted audio");
|
|
847
|
+
this.dashPlayer.setMute(true);
|
|
848
|
+
this.dashPlayer.play();
|
|
849
|
+
} else {
|
|
850
|
+
this.tryNextTech();
|
|
851
|
+
}
|
|
822
852
|
}
|
|
823
853
|
makeDashPlayerVisibleWhenInitialized() {
|
|
824
854
|
this.dashPlayer.on(dashjs.MediaPlayer.events.STREAM_INITIALIZED, event => {
|
package/dist/es/index.d.ts
CHANGED
|
@@ -55,11 +55,14 @@ export declare class WebPlayer {
|
|
|
55
55
|
*/
|
|
56
56
|
autoPlay: boolean;
|
|
57
57
|
/**
|
|
58
|
-
* mute: if
|
|
59
|
-
* default value is true because of browser's autoplay policy.
|
|
58
|
+
* mute: if false the player will try to auto play the stream with audio if it fails player will mute the audio and try again to autoplay it.
|
|
60
59
|
* It will be taken from url parameter "mute".
|
|
61
60
|
*/
|
|
62
61
|
mute: boolean;
|
|
62
|
+
/**
|
|
63
|
+
* Force the Player to play with audio Auto Play might not work.
|
|
64
|
+
*/
|
|
65
|
+
forcePlayWithAudio: boolean;
|
|
63
66
|
/**
|
|
64
67
|
* targetLatency: target latency in seconds. Optional. Default value is 3.
|
|
65
68
|
* It will be taken from url parameter "targetLatency".
|
|
@@ -176,6 +179,7 @@ export declare class WebPlayer {
|
|
|
176
179
|
*/
|
|
177
180
|
playViaDash(streamUrl: any): void;
|
|
178
181
|
dashLatencyTimer: NodeJS.Timeout | undefined;
|
|
182
|
+
handleDashPlayBackNotAllowed(): void;
|
|
179
183
|
makeDashPlayerVisibleWhenInitialized(): void;
|
|
180
184
|
/**
|
|
181
185
|
* destroy the dash player
|
package/dist/es/web_player.js
CHANGED
|
@@ -400,11 +400,14 @@ class WebPlayer {
|
|
|
400
400
|
*/
|
|
401
401
|
_defineProperty(this, "autoPlay", true);
|
|
402
402
|
/**
|
|
403
|
-
* mute: if
|
|
404
|
-
* default value is true because of browser's autoplay policy.
|
|
403
|
+
* mute: if false the player will try to auto play the stream with audio if it fails player will mute the audio and try again to autoplay it.
|
|
405
404
|
* It will be taken from url parameter "mute".
|
|
406
405
|
*/
|
|
407
|
-
_defineProperty(this, "mute",
|
|
406
|
+
_defineProperty(this, "mute", false);
|
|
407
|
+
/**
|
|
408
|
+
* Force the Player to play with audio Auto Play might not work.
|
|
409
|
+
*/
|
|
410
|
+
_defineProperty(this, "forcePlayWithAudio", false);
|
|
408
411
|
/**
|
|
409
412
|
* targetLatency: target latency in seconds. Optional. Default value is 3.
|
|
410
413
|
* It will be taken from url parameter "targetLatency".
|
|
@@ -581,7 +584,7 @@ class WebPlayer {
|
|
|
581
584
|
this.playType = WebPlayer.DEFAULT_PLAY_TYPE;
|
|
582
585
|
this.token = null;
|
|
583
586
|
this.autoPlay = true;
|
|
584
|
-
this.mute =
|
|
587
|
+
this.mute = false;
|
|
585
588
|
this.targetLatency = 3;
|
|
586
589
|
this.subscriberId = null;
|
|
587
590
|
this.subscriberCode = null;
|
|
@@ -605,6 +608,7 @@ class WebPlayer {
|
|
|
605
608
|
this.dashjsLoaded = false;
|
|
606
609
|
this.containerElementInitialDisplay = "block";
|
|
607
610
|
this.placeHolderElementInitialDisplay = "block";
|
|
611
|
+
this.forcePlayWithAudio = false;
|
|
608
612
|
}
|
|
609
613
|
initializeFromUrlParams() {
|
|
610
614
|
var _getUrlParameter;
|
|
@@ -630,7 +634,9 @@ class WebPlayer {
|
|
|
630
634
|
var muteLocal = getUrlParameter_1("mute", this.window.location.search);
|
|
631
635
|
if (muteLocal === "false") {
|
|
632
636
|
this.mute = false;
|
|
633
|
-
|
|
637
|
+
//user specifically asks to play with audio so if it fails in auto play, it will not try to play without audio
|
|
638
|
+
this.forcePlayWithAudio = true;
|
|
639
|
+
} else if (muteLocal === "true") {
|
|
634
640
|
this.mute = true;
|
|
635
641
|
}
|
|
636
642
|
var localTargetLatency = getUrlParameter_1("targetLatency", this.window.location.search);
|
|
@@ -802,7 +808,7 @@ class WebPlayer {
|
|
|
802
808
|
autoplay: this.autoPlay
|
|
803
809
|
});
|
|
804
810
|
this.videojsPlayer.on('error', e => {
|
|
805
|
-
Logger_1.warn("There is an error in playback: "
|
|
811
|
+
Logger_1.warn("There is an error in playback: ", e);
|
|
806
812
|
// We need to add this kind of check. If we don't add this kind of checkpoint, it will create an infinite loop
|
|
807
813
|
if (!this.errorCalled) {
|
|
808
814
|
this.errorCalled = true;
|
|
@@ -942,7 +948,16 @@ class WebPlayer {
|
|
|
942
948
|
reconnect: false //webrtc adaptor has auto reconnect scenario, just disable it, we manage it here
|
|
943
949
|
});
|
|
944
950
|
if (this.autoPlay) {
|
|
951
|
+
//try to play directly
|
|
945
952
|
this.videojsPlayer.play().catch(e => {
|
|
953
|
+
//if it's not allowed error and default value are being used, try to play it muted
|
|
954
|
+
//if this.forcePlayWithAudio is true, it means user specifically ask to do.
|
|
955
|
+
// If it's false, it's default value so that we can proceed to try to play with muted
|
|
956
|
+
//This implementation is added because of auto play policy of the browsers
|
|
957
|
+
if (e.name === "NotAllowedError" && !this.forcePlayWithAudio) {
|
|
958
|
+
this.videojsPlayer.muted(true);
|
|
959
|
+
this.videojsPlayer.play();
|
|
960
|
+
}
|
|
946
961
|
Logger_1.warn("Problem in playback. The error is " + e);
|
|
947
962
|
});
|
|
948
963
|
}
|
|
@@ -1102,11 +1117,26 @@ class WebPlayer {
|
|
|
1102
1117
|
}
|
|
1103
1118
|
});
|
|
1104
1119
|
this.dashPlayer.on(dashjs.MediaPlayer.events.PLAYBACK_ERROR, event => {
|
|
1120
|
+
Logger_1.warn("dash playback error: " + event);
|
|
1105
1121
|
this.tryNextTech();
|
|
1106
1122
|
});
|
|
1107
1123
|
this.dashPlayer.on(dashjs.MediaPlayer.events.ERROR, event => {
|
|
1124
|
+
Logger_1.warn("error: " + event);
|
|
1108
1125
|
this.tryNextTech();
|
|
1109
1126
|
});
|
|
1127
|
+
this.dashPlayer.on(dashjs.MediaPlayer.events.PLAYBACK_NOT_ALLOWED, event => {
|
|
1128
|
+
Logger_1.warn("dash playback not allowed: " + event);
|
|
1129
|
+
this.handleDashPlayBackNotAllowed();
|
|
1130
|
+
});
|
|
1131
|
+
}
|
|
1132
|
+
handleDashPlayBackNotAllowed() {
|
|
1133
|
+
if (!this.forcePlayWithAudio) {
|
|
1134
|
+
Logger_1.info("Try to play with muted audio");
|
|
1135
|
+
this.dashPlayer.setMute(true);
|
|
1136
|
+
this.dashPlayer.play();
|
|
1137
|
+
} else {
|
|
1138
|
+
this.tryNextTech();
|
|
1139
|
+
}
|
|
1110
1140
|
}
|
|
1111
1141
|
makeDashPlayerVisibleWhenInitialized() {
|
|
1112
1142
|
this.dashPlayer.on(dashjs.MediaPlayer.events.STREAM_INITIALIZED, event => {
|
package/dist/index.d.ts
CHANGED
|
@@ -55,11 +55,14 @@ export declare class WebPlayer {
|
|
|
55
55
|
*/
|
|
56
56
|
autoPlay: boolean;
|
|
57
57
|
/**
|
|
58
|
-
* mute: if
|
|
59
|
-
* default value is true because of browser's autoplay policy.
|
|
58
|
+
* mute: if false the player will try to auto play the stream with audio if it fails player will mute the audio and try again to autoplay it.
|
|
60
59
|
* It will be taken from url parameter "mute".
|
|
61
60
|
*/
|
|
62
61
|
mute: boolean;
|
|
62
|
+
/**
|
|
63
|
+
* Force the Player to play with audio Auto Play might not work.
|
|
64
|
+
*/
|
|
65
|
+
forcePlayWithAudio: boolean;
|
|
63
66
|
/**
|
|
64
67
|
* targetLatency: target latency in seconds. Optional. Default value is 3.
|
|
65
68
|
* It will be taken from url parameter "targetLatency".
|
|
@@ -122,8 +125,10 @@ export declare class WebPlayer {
|
|
|
122
125
|
* Field to keep if tryNextMethod is already called
|
|
123
126
|
*/
|
|
124
127
|
tryNextTechTimer: any;
|
|
125
|
-
|
|
128
|
+
containerElementInitialDisplay: any;
|
|
129
|
+
placeHolderElementInitialDisplay: any;
|
|
126
130
|
httpBaseURL: string;
|
|
131
|
+
websocketURL: any;
|
|
127
132
|
dom: any;
|
|
128
133
|
isWindow(configOrWindow: any): any;
|
|
129
134
|
initialize(): Promise<any>;
|
|
@@ -174,6 +179,7 @@ export declare class WebPlayer {
|
|
|
174
179
|
*/
|
|
175
180
|
playViaDash(streamUrl: any): void;
|
|
176
181
|
dashLatencyTimer: NodeJS.Timeout | undefined;
|
|
182
|
+
handleDashPlayBackNotAllowed(): void;
|
|
177
183
|
makeDashPlayerVisibleWhenInitialized(): void;
|
|
178
184
|
/**
|
|
179
185
|
* destroy the dash player
|
package/dist/web_player.js
CHANGED
|
@@ -402,11 +402,14 @@ class WebPlayer {
|
|
|
402
402
|
*/
|
|
403
403
|
_defineProperty(this, "autoPlay", true);
|
|
404
404
|
/**
|
|
405
|
-
* mute: if
|
|
406
|
-
* default value is true because of browser's autoplay policy.
|
|
405
|
+
* mute: if false the player will try to auto play the stream with audio if it fails player will mute the audio and try again to autoplay it.
|
|
407
406
|
* It will be taken from url parameter "mute".
|
|
408
407
|
*/
|
|
409
|
-
_defineProperty(this, "mute",
|
|
408
|
+
_defineProperty(this, "mute", false);
|
|
409
|
+
/**
|
|
410
|
+
* Force the Player to play with audio Auto Play might not work.
|
|
411
|
+
*/
|
|
412
|
+
_defineProperty(this, "forcePlayWithAudio", false);
|
|
410
413
|
/**
|
|
411
414
|
* targetLatency: target latency in seconds. Optional. Default value is 3.
|
|
412
415
|
* It will be taken from url parameter "targetLatency".
|
|
@@ -583,7 +586,7 @@ class WebPlayer {
|
|
|
583
586
|
this.playType = WebPlayer.DEFAULT_PLAY_TYPE;
|
|
584
587
|
this.token = null;
|
|
585
588
|
this.autoPlay = true;
|
|
586
|
-
this.mute =
|
|
589
|
+
this.mute = false;
|
|
587
590
|
this.targetLatency = 3;
|
|
588
591
|
this.subscriberId = null;
|
|
589
592
|
this.subscriberCode = null;
|
|
@@ -607,6 +610,7 @@ class WebPlayer {
|
|
|
607
610
|
this.dashjsLoaded = false;
|
|
608
611
|
this.containerElementInitialDisplay = "block";
|
|
609
612
|
this.placeHolderElementInitialDisplay = "block";
|
|
613
|
+
this.forcePlayWithAudio = false;
|
|
610
614
|
}
|
|
611
615
|
initializeFromUrlParams() {
|
|
612
616
|
var _getUrlParameter;
|
|
@@ -632,7 +636,9 @@ class WebPlayer {
|
|
|
632
636
|
var muteLocal = getUrlParameter_1("mute", this.window.location.search);
|
|
633
637
|
if (muteLocal === "false") {
|
|
634
638
|
this.mute = false;
|
|
635
|
-
|
|
639
|
+
//user specifically asks to play with audio so if it fails in auto play, it will not try to play without audio
|
|
640
|
+
this.forcePlayWithAudio = true;
|
|
641
|
+
} else if (muteLocal === "true") {
|
|
636
642
|
this.mute = true;
|
|
637
643
|
}
|
|
638
644
|
var localTargetLatency = getUrlParameter_1("targetLatency", this.window.location.search);
|
|
@@ -804,7 +810,7 @@ class WebPlayer {
|
|
|
804
810
|
autoplay: this.autoPlay
|
|
805
811
|
});
|
|
806
812
|
this.videojsPlayer.on('error', e => {
|
|
807
|
-
Logger_1.warn("There is an error in playback: "
|
|
813
|
+
Logger_1.warn("There is an error in playback: ", e);
|
|
808
814
|
// We need to add this kind of check. If we don't add this kind of checkpoint, it will create an infinite loop
|
|
809
815
|
if (!this.errorCalled) {
|
|
810
816
|
this.errorCalled = true;
|
|
@@ -944,7 +950,16 @@ class WebPlayer {
|
|
|
944
950
|
reconnect: false //webrtc adaptor has auto reconnect scenario, just disable it, we manage it here
|
|
945
951
|
});
|
|
946
952
|
if (this.autoPlay) {
|
|
953
|
+
//try to play directly
|
|
947
954
|
this.videojsPlayer.play().catch(e => {
|
|
955
|
+
//if it's not allowed error and default value are being used, try to play it muted
|
|
956
|
+
//if this.forcePlayWithAudio is true, it means user specifically ask to do.
|
|
957
|
+
// If it's false, it's default value so that we can proceed to try to play with muted
|
|
958
|
+
//This implementation is added because of auto play policy of the browsers
|
|
959
|
+
if (e.name === "NotAllowedError" && !this.forcePlayWithAudio) {
|
|
960
|
+
this.videojsPlayer.muted(true);
|
|
961
|
+
this.videojsPlayer.play();
|
|
962
|
+
}
|
|
948
963
|
Logger_1.warn("Problem in playback. The error is " + e);
|
|
949
964
|
});
|
|
950
965
|
}
|
|
@@ -1104,11 +1119,26 @@ class WebPlayer {
|
|
|
1104
1119
|
}
|
|
1105
1120
|
});
|
|
1106
1121
|
this.dashPlayer.on(dashjs.MediaPlayer.events.PLAYBACK_ERROR, event => {
|
|
1122
|
+
Logger_1.warn("dash playback error: " + event);
|
|
1107
1123
|
this.tryNextTech();
|
|
1108
1124
|
});
|
|
1109
1125
|
this.dashPlayer.on(dashjs.MediaPlayer.events.ERROR, event => {
|
|
1126
|
+
Logger_1.warn("error: " + event);
|
|
1110
1127
|
this.tryNextTech();
|
|
1111
1128
|
});
|
|
1129
|
+
this.dashPlayer.on(dashjs.MediaPlayer.events.PLAYBACK_NOT_ALLOWED, event => {
|
|
1130
|
+
Logger_1.warn("dash playback not allowed: " + event);
|
|
1131
|
+
this.handleDashPlayBackNotAllowed();
|
|
1132
|
+
});
|
|
1133
|
+
}
|
|
1134
|
+
handleDashPlayBackNotAllowed() {
|
|
1135
|
+
if (!this.forcePlayWithAudio) {
|
|
1136
|
+
Logger_1.info("Try to play with muted audio");
|
|
1137
|
+
this.dashPlayer.setMute(true);
|
|
1138
|
+
this.dashPlayer.play();
|
|
1139
|
+
} else {
|
|
1140
|
+
this.tryNextTech();
|
|
1141
|
+
}
|
|
1112
1142
|
}
|
|
1113
1143
|
makeDashPlayerVisibleWhenInitialized() {
|
|
1114
1144
|
this.dashPlayer.on(dashjs.MediaPlayer.events.STREAM_INITIALIZED, event => {
|
package/package.json
CHANGED
package/src/web_player.js
CHANGED
|
@@ -78,17 +78,22 @@ export class WebPlayer {
|
|
|
78
78
|
autoPlay = true;
|
|
79
79
|
|
|
80
80
|
/**
|
|
81
|
-
* mute: if
|
|
82
|
-
* default value is true because of browser's autoplay policy.
|
|
81
|
+
* mute: if false the player will try to auto play the stream with audio if it fails player will mute the audio and try again to autoplay it.
|
|
83
82
|
* It will be taken from url parameter "mute".
|
|
84
83
|
*/
|
|
85
|
-
mute =
|
|
84
|
+
mute = false;
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Force the Player to play with audio Auto Play might not work.
|
|
88
|
+
*/
|
|
89
|
+
forcePlayWithAudio = false;
|
|
86
90
|
|
|
87
91
|
/**
|
|
88
92
|
* targetLatency: target latency in seconds. Optional. Default value is 3.
|
|
89
93
|
* It will be taken from url parameter "targetLatency".
|
|
90
94
|
* It's used for dash(cmaf) playback.
|
|
91
95
|
*/
|
|
96
|
+
|
|
92
97
|
targetLatency = 3;
|
|
93
98
|
|
|
94
99
|
/**
|
|
@@ -161,6 +166,7 @@ export class WebPlayer {
|
|
|
161
166
|
*/
|
|
162
167
|
tryNextTechTimer;
|
|
163
168
|
|
|
169
|
+
|
|
164
170
|
constructor(configOrWindow, containerElement, placeHolderElement) {
|
|
165
171
|
|
|
166
172
|
WebPlayer.DEFAULT_PLAY_ORDER = ["webrtc", "hls"];;
|
|
@@ -312,7 +318,7 @@ export class WebPlayer {
|
|
|
312
318
|
this.playType = WebPlayer.DEFAULT_PLAY_TYPE;
|
|
313
319
|
this.token = null;
|
|
314
320
|
this.autoPlay = true;
|
|
315
|
-
this.mute =
|
|
321
|
+
this.mute = false;
|
|
316
322
|
this.targetLatency = 3;
|
|
317
323
|
this.subscriberId = null;
|
|
318
324
|
this.subscriberCode = null;
|
|
@@ -336,6 +342,7 @@ export class WebPlayer {
|
|
|
336
342
|
this.dashjsLoaded = false;
|
|
337
343
|
this.containerElementInitialDisplay = "block";
|
|
338
344
|
this.placeHolderElementInitialDisplay = "block";
|
|
345
|
+
this.forcePlayWithAudio = false;
|
|
339
346
|
}
|
|
340
347
|
|
|
341
348
|
initializeFromUrlParams() {
|
|
@@ -365,11 +372,13 @@ export class WebPlayer {
|
|
|
365
372
|
|
|
366
373
|
let muteLocal = getUrlParameter("mute", this.window.location.search);
|
|
367
374
|
if (muteLocal === "false") {
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
375
|
+
this.mute = false;
|
|
376
|
+
//user specifically asks to play with audio so if it fails in auto play, it will not try to play without audio
|
|
377
|
+
this.forcePlayWithAudio = true;
|
|
378
|
+
}else if(muteLocal === "true"){
|
|
379
|
+
this.mute = true;
|
|
380
|
+
}
|
|
381
|
+
|
|
373
382
|
|
|
374
383
|
let localTargetLatency = getUrlParameter("targetLatency", this.window.location.search);
|
|
375
384
|
if (localTargetLatency != null) {
|
|
@@ -571,7 +580,7 @@ export class WebPlayer {
|
|
|
571
580
|
});
|
|
572
581
|
|
|
573
582
|
this.videojsPlayer.on('error', (e) => {
|
|
574
|
-
Logger.warn("There is an error in playback: "
|
|
583
|
+
Logger.warn("There is an error in playback: ", e);
|
|
575
584
|
// We need to add this kind of check. If we don't add this kind of checkpoint, it will create an infinite loop
|
|
576
585
|
if (!this.errorCalled) {
|
|
577
586
|
this.errorCalled = true;
|
|
@@ -739,9 +748,19 @@ export class WebPlayer {
|
|
|
739
748
|
});
|
|
740
749
|
|
|
741
750
|
if (this.autoPlay) {
|
|
751
|
+
//try to play directly
|
|
742
752
|
this.videojsPlayer.play().catch((e) => {
|
|
743
|
-
|
|
744
|
-
|
|
753
|
+
|
|
754
|
+
//if it's not allowed error and default value are being used, try to play it muted
|
|
755
|
+
//if this.forcePlayWithAudio is true, it means user specifically ask to do.
|
|
756
|
+
// If it's false, it's default value so that we can proceed to try to play with muted
|
|
757
|
+
//This implementation is added because of auto play policy of the browsers
|
|
758
|
+
if (e.name === "NotAllowedError" && !this.forcePlayWithAudio) {
|
|
759
|
+
this.videojsPlayer.muted(true);
|
|
760
|
+
this.videojsPlayer.play();
|
|
761
|
+
}
|
|
762
|
+
Logger.warn("Problem in playback. The error is " + e);
|
|
763
|
+
});
|
|
745
764
|
}
|
|
746
765
|
}
|
|
747
766
|
|
|
@@ -926,11 +945,29 @@ export class WebPlayer {
|
|
|
926
945
|
}
|
|
927
946
|
});
|
|
928
947
|
this.dashPlayer.on(dashjs.MediaPlayer.events.PLAYBACK_ERROR, (event) => {
|
|
948
|
+
Logger.warn("dash playback error: " + event);
|
|
929
949
|
this.tryNextTech();
|
|
930
950
|
});
|
|
931
951
|
this.dashPlayer.on(dashjs.MediaPlayer.events.ERROR, (event) => {
|
|
952
|
+
Logger.warn("error: " + event);
|
|
932
953
|
this.tryNextTech();
|
|
933
954
|
});
|
|
955
|
+
|
|
956
|
+
this.dashPlayer.on(dashjs.MediaPlayer.events.PLAYBACK_NOT_ALLOWED, (event) => {
|
|
957
|
+
Logger.warn("dash playback not allowed: " + event);
|
|
958
|
+
this.handleDashPlayBackNotAllowed();
|
|
959
|
+
});
|
|
960
|
+
}
|
|
961
|
+
|
|
962
|
+
handleDashPlayBackNotAllowed() {
|
|
963
|
+
if (!this.forcePlayWithAudio) {
|
|
964
|
+
Logger.info("Try to play with muted audio");
|
|
965
|
+
this.dashPlayer.setMute(true);
|
|
966
|
+
this.dashPlayer.play();
|
|
967
|
+
}
|
|
968
|
+
else {
|
|
969
|
+
this.tryNextTech();
|
|
970
|
+
}
|
|
934
971
|
}
|
|
935
972
|
|
|
936
973
|
makeDashPlayerVisibleWhenInitialized() {
|
|
@@ -45,8 +45,8 @@ describe("WebPlayer", function() {
|
|
|
45
45
|
//the following is a test autoPlay is still true in mobile. We just try to play the stream if mobile browser can play or not
|
|
46
46
|
//in autoPlay mode
|
|
47
47
|
expect(player.autoPlay).to.true;
|
|
48
|
-
expect(player.mute).to.
|
|
49
|
-
expect(player.isMuted()).to.be.
|
|
48
|
+
expect(player.mute).to.false;
|
|
49
|
+
expect(player.isMuted()).to.be.false;
|
|
50
50
|
expect(player.targetLatency).to.equal(3);
|
|
51
51
|
expect(player.subscriberId).to.be.null;
|
|
52
52
|
expect(player.subscriberCode).to.be.null;
|
|
@@ -164,8 +164,8 @@ describe("WebPlayer", function() {
|
|
|
164
164
|
//the following is a test autoPlay is still true in mobile. We just try to play the stream if mobile browser can play or not
|
|
165
165
|
//in autoPlay mode
|
|
166
166
|
expect(player.autoPlay).to.true;
|
|
167
|
-
expect(player.mute).to.
|
|
168
|
-
expect(player.isMuted()).to.be.
|
|
167
|
+
expect(player.mute).to.false;
|
|
168
|
+
expect(player.isMuted()).to.be.false;
|
|
169
169
|
expect(player.targetLatency).to.equal(3);
|
|
170
170
|
expect(player.subscriberId).to.be.null;
|
|
171
171
|
expect(player.subscriberCode).to.be.null;
|
|
@@ -786,6 +786,70 @@ describe("WebPlayer", function() {
|
|
|
786
786
|
|
|
787
787
|
|
|
788
788
|
});
|
|
789
|
+
|
|
790
|
+
it("testAutoPlay",async function(){
|
|
791
|
+
var videoContainer = document.createElement("video_container");
|
|
792
|
+
|
|
793
|
+
var placeHolder = document.createElement("place_holder");
|
|
794
|
+
|
|
795
|
+
var locationComponent = { href: 'http://example.com?id=stream123.mp4', search: "?id=stream123.mp4", pathname: "/", protocol: "http:" };
|
|
796
|
+
var windowComponent = { location : locationComponent,
|
|
797
|
+
document: document,
|
|
798
|
+
addEventListener: window.addEventListener};
|
|
799
|
+
|
|
800
|
+
var player = new WebPlayer(windowComponent, videoContainer, placeHolder);
|
|
801
|
+
let vjsMock = videojs(WebPlayer.VIDEO_PLAYER_ID, {
|
|
802
|
+
poster: "test",
|
|
803
|
+
liveui:true ,
|
|
804
|
+
liveTracker: {
|
|
805
|
+
trackingThreshold: 0
|
|
806
|
+
},
|
|
807
|
+
html5: {
|
|
808
|
+
vhs: {
|
|
809
|
+
limitRenditionByPlayerDimensions: false
|
|
810
|
+
}
|
|
811
|
+
},
|
|
812
|
+
controls: true,
|
|
813
|
+
class: 'video-js vjs-default-skin vjs-big-play-centered',
|
|
814
|
+
muted: false,
|
|
815
|
+
preload: "auto",
|
|
816
|
+
autoplay: true
|
|
817
|
+
});
|
|
818
|
+
|
|
819
|
+
const mockVideoJS = sinon.stub(window, 'videojs').callsFake(()=>{return vjsMock});
|
|
820
|
+
var muted = sinon.replace(vjsMock, "muted", sinon.fake());
|
|
821
|
+
let play = sinon.stub(vjsMock, 'play').callsFake(()=>{
|
|
822
|
+
return Promise.resolve();
|
|
823
|
+
});
|
|
824
|
+
await player.playIfExists("webrtc"); // autoplay worked with audio
|
|
825
|
+
expect(play.calledOnce).to.be.true;
|
|
826
|
+
expect(muted.notCalled).to.be.true;
|
|
827
|
+
|
|
828
|
+
play.restore();
|
|
829
|
+
|
|
830
|
+
play = sinon.stub(vjsMock, 'play').callsFake(()=>{
|
|
831
|
+
return Promise.reject(new DOMException("NotAllowedError","NotAllowedError"));
|
|
832
|
+
});
|
|
833
|
+
player.forcePlayWithAudio = true;
|
|
834
|
+
|
|
835
|
+
await player.playIfExists("webrtc"); // autoplay failed force play with audio
|
|
836
|
+
expect(play.calledOnce).to.be.true;
|
|
837
|
+
expect(muted.notCalled).to.be.true;
|
|
838
|
+
|
|
839
|
+
play.restore();
|
|
840
|
+
|
|
841
|
+
|
|
842
|
+
play = sinon.stub(vjsMock, 'play').callsFake(()=>{
|
|
843
|
+
return Promise.reject(new DOMException("NotAllowedError","NotAllowedError"));
|
|
844
|
+
});
|
|
845
|
+
player.forcePlayWithAudio = false;
|
|
846
|
+
await player.playIfExists("webrtc"); // autoplay failed try to play without audio
|
|
847
|
+
|
|
848
|
+
expect(play.calledTwice).to.be.true;
|
|
849
|
+
expect(muted.calledWithMatch(true)).to.be.true;
|
|
850
|
+
|
|
851
|
+
sinon.restore();
|
|
852
|
+
})
|
|
789
853
|
|
|
790
854
|
|
|
791
855
|
it("webrtc-info-event", async function() {
|
|
@@ -885,9 +949,52 @@ describe("WebPlayer", function() {
|
|
|
885
949
|
result = player.sendWebRTCData("data");
|
|
886
950
|
expect(result).to.be.false;
|
|
887
951
|
expect(sendDataViaWebRTC.callCount).to.be.equal(1);
|
|
952
|
+
});
|
|
953
|
+
|
|
954
|
+
|
|
955
|
+
it("handleDashPlayBackNotAllowed", async function(){
|
|
956
|
+
|
|
957
|
+
this.timeout(10000);
|
|
958
|
+
var videoContainer = document.createElement("video_container");
|
|
959
|
+
|
|
960
|
+
|
|
961
|
+
|
|
962
|
+
var player = new WebPlayer({
|
|
963
|
+
streamId:"streamConfig",
|
|
964
|
+
}, videoContainer, null);
|
|
965
|
+
|
|
966
|
+
|
|
967
|
+
{
|
|
968
|
+
player.playOrder = ["dash"];
|
|
969
|
+
await player.initialize().then(()=> {
|
|
970
|
+
|
|
971
|
+
}).catch((err) => {
|
|
972
|
+
expect.fail("it should not fail because we skip videojs and dash is already loaded");
|
|
973
|
+
});
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
player.dashPlayer = window.dashjs.MediaPlayer().create();
|
|
977
|
+
|
|
978
|
+
var setMute = sinon.replace(player.dashPlayer, "setMute", sinon.fake());
|
|
979
|
+
var play = sinon.replace(player.dashPlayer, "play", sinon.fake());
|
|
980
|
+
var nextTech = sinon.replace(player, "tryNextTech", sinon.fake());
|
|
981
|
+
|
|
982
|
+
expect(player.forcePlayWithAudio).to.be.false;
|
|
983
|
+
player.handleDashPlayBackNotAllowed();
|
|
984
|
+
expect(setMute.calledOnce).to.be.true;
|
|
985
|
+
expect(play.calledOnce).to.be.true;
|
|
986
|
+
expect(nextTech.notCalled).to.be.true;
|
|
987
|
+
|
|
988
|
+
expect(setMute.calledWithExactly(true)).to.be.true;
|
|
989
|
+
|
|
990
|
+
|
|
991
|
+
player.forcePlayWithAudio = true;
|
|
992
|
+
player.handleDashPlayBackNotAllowed();
|
|
993
|
+
expect(setMute.calledOnce).to.be.true;
|
|
994
|
+
expect(play.calledOnce).to.be.true;
|
|
995
|
+
expect(nextTech.calledOnce).to.be.true;
|
|
996
|
+
|
|
888
997
|
|
|
889
|
-
|
|
890
|
-
|
|
891
998
|
|
|
892
999
|
});
|
|
893
1000
|
|
package/.project
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
-
<projectDescription>
|
|
3
|
-
<name>Embedded-Player</name>
|
|
4
|
-
<comment></comment>
|
|
5
|
-
<projects>
|
|
6
|
-
</projects>
|
|
7
|
-
<buildSpec>
|
|
8
|
-
<buildCommand>
|
|
9
|
-
<name>org.eclipse.wst.validation.validationbuilder</name>
|
|
10
|
-
<arguments>
|
|
11
|
-
</arguments>
|
|
12
|
-
</buildCommand>
|
|
13
|
-
</buildSpec>
|
|
14
|
-
<natures>
|
|
15
|
-
<nature>org.eclipse.wst.jsdt.core.jsNature</nature>
|
|
16
|
-
</natures>
|
|
17
|
-
</projectDescription>
|
package/.settings/.jsdtscope
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
-
<classpath>
|
|
3
|
-
<classpathentry kind="con" path="org.eclipse.wst.jsdt.launching.JRE_CONTAINER"/>
|
|
4
|
-
<classpathentry kind="con" path="org.eclipse.wst.jsdt.launching.baseBrowserLibrary"/>
|
|
5
|
-
<classpathentry kind="src" path=""/>
|
|
6
|
-
<classpathentry kind="output" path=""/>
|
|
7
|
-
</classpath>
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
org.eclipse.wst.jsdt.launching.JRE_CONTAINER
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
Global
|