@saooti/octopus-sdk 37.0.15 → 37.0.17
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/index.html +9 -0
- package/package.json +3 -1
- package/src/assets/share.scss +2 -2
- package/src/components/display/list/SwiperList.vue +1 -1
- package/src/components/display/podcasts/PodcastImage.vue +23 -5
- package/src/components/display/podcasts/PodcastModuleBox.vue +1 -5
- package/src/components/display/sharing/ShareButtons.vue +2 -0
- package/src/components/misc/player/PlayerComponent.vue +49 -40
- package/src/components/misc/player/PlayerVideo.vue +91 -0
- package/src/components/misc/player/PlayerVideoDigiteka.vue +62 -0
- package/src/components/misc/player/PlayerVideoHls.vue +176 -0
- package/src/locale/de.ts +1 -0
- package/src/locale/en.ts +1 -0
- package/src/locale/es.ts +1 -0
- package/src/locale/fr.ts +1 -0
- package/src/locale/it.ts +1 -0
- package/src/locale/sl.ts +1 -0
- package/src/stores/PlayerStore.ts +8 -3
- package/src/stores/class/conference/conference.ts +1 -0
- package/src/stores/class/general/podcast.ts +3 -0
- package/src/stores/class/general/video.ts +8 -0
package/index.html
CHANGED
|
@@ -16,5 +16,14 @@
|
|
|
16
16
|
<div id="app"></div>
|
|
17
17
|
<!-- built files will be auto injected -->
|
|
18
18
|
</body>
|
|
19
|
+
<!-- Test digiteka video -->
|
|
20
|
+
<script type="text/javascript">
|
|
21
|
+
var _ultimedia_host = (window.location.protocol == 'https:' ? 'https' : 'http') + "://www.ultimedia.com";
|
|
22
|
+
var _ultimedia_script = document.createElement("script");
|
|
23
|
+
|
|
24
|
+
_ultimedia_script.setAttribute("type", "text/javascript");
|
|
25
|
+
_ultimedia_script.setAttribute("src", _ultimedia_host + '/js/common/visible_player.js');
|
|
26
|
+
document.getElementsByTagName('head')[0].appendChild(_ultimedia_script);
|
|
27
|
+
</script>
|
|
19
28
|
<script type="module" src="./src/main.ts"></script>
|
|
20
29
|
</html>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@saooti/octopus-sdk",
|
|
3
|
-
"version": "37.0.
|
|
3
|
+
"version": "37.0.17",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Javascript SDK for using octopus",
|
|
6
6
|
"author": "Saooti",
|
|
@@ -14,6 +14,8 @@
|
|
|
14
14
|
"test": "jest --coverage"
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
|
+
"@clappr/core": "0.4.27",
|
|
18
|
+
"@clappr/hlsjs-playback": "^1.1.0",
|
|
17
19
|
"@popperjs/core": "^2.11.8",
|
|
18
20
|
"@saooti/octopus-api": "^0.34.3",
|
|
19
21
|
"@tiptap/extension-link": "^2.0.4",
|
package/src/assets/share.scss
CHANGED
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
v-if="hidePlay || recordingLive"
|
|
33
33
|
class="image-play-button"
|
|
34
34
|
:class="classicPodcastPlay ? '' : 'transparent-background'"
|
|
35
|
-
@click="play"
|
|
35
|
+
@click="play(false)"
|
|
36
36
|
>
|
|
37
37
|
<div v-if="!isLiveToBeRecorded" class="icon-container">
|
|
38
38
|
<div v-if="!playingPodcast" :title="$t('Play')" class="saooti-play" />
|
|
@@ -61,6 +61,11 @@
|
|
|
61
61
|
{{ textVisible }}
|
|
62
62
|
</div>
|
|
63
63
|
</button>
|
|
64
|
+
<button
|
|
65
|
+
v-if="isVideoPodcast"
|
|
66
|
+
class="btn admin-button btn-play-video saooti-video"
|
|
67
|
+
@click="play(true)"
|
|
68
|
+
></button>
|
|
64
69
|
<div
|
|
65
70
|
v-if="displayDescription && isMobile"
|
|
66
71
|
class="background-icon bg-primary saooti-arrow-up"
|
|
@@ -102,7 +107,11 @@ export default defineComponent({
|
|
|
102
107
|
"playerPodcast",
|
|
103
108
|
"playerLive",
|
|
104
109
|
"playerStatus",
|
|
110
|
+
"playerVideo"
|
|
105
111
|
]),
|
|
112
|
+
isVideoPodcast(): boolean{
|
|
113
|
+
return this.fetchConference?.videoProfile?.includes('video_') || undefined!==this.podcast.video?.videoId;
|
|
114
|
+
},
|
|
106
115
|
playingPodcast() {
|
|
107
116
|
return (
|
|
108
117
|
this.playerPodcast?.podcastId === this.podcast.podcastId ||
|
|
@@ -248,21 +257,21 @@ export default defineComponent({
|
|
|
248
257
|
|
|
249
258
|
methods: {
|
|
250
259
|
...mapActions(usePlayerStore, ["playerChangeStatus", "playerPlay"]),
|
|
251
|
-
play(): void {
|
|
260
|
+
play(isVideo: boolean): void {
|
|
252
261
|
if (this.isLiveToBeRecorded) {
|
|
253
262
|
return;
|
|
254
263
|
}
|
|
255
|
-
if (this.playingPodcast) {
|
|
264
|
+
if (this.playingPodcast && isVideo===this.playerVideo) {
|
|
256
265
|
this.playerChangeStatus("PLAYING" === this.playerStatus);
|
|
257
266
|
return;
|
|
258
267
|
}
|
|
259
268
|
if (!this.recordingLive) {
|
|
260
|
-
this.playerPlay(this.podcast);
|
|
269
|
+
this.playerPlay(this.podcast, isVideo);
|
|
261
270
|
} else {
|
|
262
271
|
this.playerPlay({
|
|
263
272
|
...this.podcast,
|
|
264
273
|
...{ conferenceId: this.fetchConference?.conferenceId },
|
|
265
|
-
});
|
|
274
|
+
}, isVideo);
|
|
266
275
|
}
|
|
267
276
|
if (this.clickPlayGoPage) {
|
|
268
277
|
this.$router.push("/main/pub/podcast/" + this.podcast.podcastId);
|
|
@@ -310,6 +319,15 @@ export default defineComponent({
|
|
|
310
319
|
background-color: rgba(255, 255, 255, 0.5);
|
|
311
320
|
}
|
|
312
321
|
|
|
322
|
+
.btn.btn-play-video{
|
|
323
|
+
position: absolute;
|
|
324
|
+
bottom: 0;
|
|
325
|
+
right: 0;
|
|
326
|
+
margin: 0.5rem;
|
|
327
|
+
background: $primaryColorLessTransparent !important;
|
|
328
|
+
color:white !important
|
|
329
|
+
}
|
|
330
|
+
|
|
313
331
|
.image-play-button .play-button-error-icon {
|
|
314
332
|
background: #0000009d !important;
|
|
315
333
|
cursor: default !important;
|
|
@@ -17,7 +17,6 @@
|
|
|
17
17
|
:playing-podcast="playingPodcast"
|
|
18
18
|
:fetch-conference="fetchConference"
|
|
19
19
|
:is-animator-live="isOctopusAndAnimator"
|
|
20
|
-
@play-podcast="playPodcast"
|
|
21
20
|
/>
|
|
22
21
|
<div class="d-flex justify-content-between flex-wrap mb-2">
|
|
23
22
|
<div v-if="0 !== date.length" :class="!isLiveReady ? 'me-5' : ''">
|
|
@@ -173,7 +172,7 @@ export default defineComponent({
|
|
|
173
172
|
fetchConference: { default: undefined, type: Object as () => Conference },
|
|
174
173
|
},
|
|
175
174
|
|
|
176
|
-
emits: ["
|
|
175
|
+
emits: ["updatePodcast"],
|
|
177
176
|
|
|
178
177
|
computed: {
|
|
179
178
|
errorMessage(): string {
|
|
@@ -261,9 +260,6 @@ export default defineComponent({
|
|
|
261
260
|
},
|
|
262
261
|
},
|
|
263
262
|
methods: {
|
|
264
|
-
playPodcast(podcast: Podcast): void {
|
|
265
|
-
this.$emit("playPodcast", podcast);
|
|
266
|
-
},
|
|
267
263
|
removeDeleted(): void {
|
|
268
264
|
if (window.history.length > 1) {
|
|
269
265
|
this.$router.go(-1);
|
|
@@ -1,48 +1,52 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div
|
|
3
3
|
class="player-container"
|
|
4
|
+
:class="playerVideo? 'player-video':''"
|
|
4
5
|
:style="{ height: playerHeight }"
|
|
5
6
|
@transitionend="onHidden"
|
|
6
7
|
>
|
|
7
8
|
<template v-if="display">
|
|
8
|
-
<
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
9
|
+
<PlayerVideo v-if="playerVideo"/>
|
|
10
|
+
<template v-else>
|
|
11
|
+
<audio
|
|
12
|
+
id="audio-player"
|
|
13
|
+
:src="!playerLive && !playerRadio ? audioUrlToPlay : undefined"
|
|
14
|
+
autoplay
|
|
15
|
+
@timeupdate="onTimeUpdate"
|
|
16
|
+
@ended="onFinished"
|
|
17
|
+
@playing="onPlay"
|
|
18
|
+
@durationChange="onTimeUpdate"
|
|
19
|
+
@error="onError"
|
|
20
|
+
@seeked="onSeeked"
|
|
21
|
+
@pause="onPause"
|
|
22
|
+
/>
|
|
23
|
+
<PlayerCompact
|
|
24
|
+
v-if="!playerLargeVersion"
|
|
25
|
+
v-model:notListenTime="notListenTime"
|
|
26
|
+
:player-error="playerError"
|
|
27
|
+
:comments="comments"
|
|
28
|
+
:display-alert-bar="displayAlertBar"
|
|
29
|
+
:percent-live-progress="percentLiveProgress"
|
|
30
|
+
:duration-live-position="durationLivePosition"
|
|
31
|
+
:listen-time="listenTime"
|
|
32
|
+
:hlsReady="hlsReady"
|
|
33
|
+
@stop-player="stopPlayer"
|
|
34
|
+
@change-player-large-version="playerUpdateLargeVersion(true)"
|
|
35
|
+
/>
|
|
36
|
+
<PlayerLarge
|
|
37
|
+
v-else
|
|
38
|
+
v-model:notListenTime="notListenTime"
|
|
39
|
+
:player-error="playerError"
|
|
40
|
+
:comments="comments"
|
|
41
|
+
:display-alert-bar="displayAlertBar"
|
|
42
|
+
:percent-live-progress="percentLiveProgress"
|
|
43
|
+
:duration-live-position="durationLivePosition"
|
|
44
|
+
:listen-time="listenTime"
|
|
45
|
+
:hlsReady="hlsReady"
|
|
46
|
+
@stop-player="stopPlayer"
|
|
47
|
+
@change-player-large-version="playerUpdateLargeVersion(false)"
|
|
48
|
+
/>
|
|
49
|
+
</template>
|
|
46
50
|
</template>
|
|
47
51
|
</div>
|
|
48
52
|
</template>
|
|
@@ -53,13 +57,17 @@ import PlayerCompact from "../player/PlayerCompact.vue";
|
|
|
53
57
|
import PlayerLarge from "../player/PlayerLarge.vue";
|
|
54
58
|
import { usePlayerStore } from "@/stores/PlayerStore";
|
|
55
59
|
import { mapState, mapActions } from "pinia";
|
|
56
|
-
import { defineComponent } from "vue";
|
|
60
|
+
import { defineComponent, defineAsyncComponent } from "vue";
|
|
61
|
+
const PlayerVideo = defineAsyncComponent(
|
|
62
|
+
() => import("./PlayerVideo.vue"),
|
|
63
|
+
);
|
|
57
64
|
export default defineComponent({
|
|
58
65
|
name: "PlayerComponent",
|
|
59
66
|
|
|
60
67
|
components: {
|
|
61
68
|
PlayerCompact,
|
|
62
69
|
PlayerLarge,
|
|
70
|
+
PlayerVideo
|
|
63
71
|
},
|
|
64
72
|
mixins: [playerLogic],
|
|
65
73
|
emits: ["hide"],
|
|
@@ -85,6 +93,7 @@ export default defineComponent({
|
|
|
85
93
|
"playerStatus",
|
|
86
94
|
"playerHeight",
|
|
87
95
|
"playerLargeVersion",
|
|
96
|
+
"playerVideo"
|
|
88
97
|
]),
|
|
89
98
|
display() {
|
|
90
99
|
return "STOPPED" !== this.playerStatus;
|
|
@@ -120,7 +129,7 @@ export default defineComponent({
|
|
|
120
129
|
|
|
121
130
|
<style lang="scss">
|
|
122
131
|
.octopus-app {
|
|
123
|
-
.player-container
|
|
132
|
+
.player-container{
|
|
124
133
|
max-height: 94%;
|
|
125
134
|
position: sticky;
|
|
126
135
|
overflow: hidden;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<teleport to=".octopus-app">
|
|
3
|
+
<template v-if="playerVideo">
|
|
4
|
+
<button
|
|
5
|
+
class="btn btn-transparent video-close saooti-remove"
|
|
6
|
+
@click="closePlayer"
|
|
7
|
+
/>
|
|
8
|
+
<div class="video-wrapper">
|
|
9
|
+
<PlayerVideoDigiteka
|
|
10
|
+
v-if="!playerLive"
|
|
11
|
+
/>
|
|
12
|
+
<PlayerVideoHls
|
|
13
|
+
v-else
|
|
14
|
+
:hls-url="hlsUrl"
|
|
15
|
+
/>
|
|
16
|
+
</div>
|
|
17
|
+
</template>
|
|
18
|
+
</teleport>
|
|
19
|
+
</template>
|
|
20
|
+
<script lang="ts">
|
|
21
|
+
import { state } from "../../../stores/ParamSdkStore";
|
|
22
|
+
import { usePlayerStore } from "@/stores/PlayerStore";
|
|
23
|
+
import { mapState, mapActions } from "pinia";
|
|
24
|
+
import { defineComponent, defineAsyncComponent } from "vue";
|
|
25
|
+
const PlayerVideoDigiteka = defineAsyncComponent(
|
|
26
|
+
() => import("./PlayerVideoDigiteka.vue"),
|
|
27
|
+
);
|
|
28
|
+
const PlayerVideoHls = defineAsyncComponent(
|
|
29
|
+
() => import("./PlayerVideoHls.vue"),
|
|
30
|
+
);
|
|
31
|
+
export default defineComponent({
|
|
32
|
+
name: "PlayerVideo",
|
|
33
|
+
|
|
34
|
+
components: {
|
|
35
|
+
PlayerVideoDigiteka,
|
|
36
|
+
PlayerVideoHls
|
|
37
|
+
},
|
|
38
|
+
data() {
|
|
39
|
+
return {
|
|
40
|
+
};
|
|
41
|
+
},
|
|
42
|
+
computed: {
|
|
43
|
+
...mapState(usePlayerStore, ["playerVideo", "playerLive"]),
|
|
44
|
+
hlsUrl(): string{
|
|
45
|
+
if(!this.playerLive){return "";}
|
|
46
|
+
return `${state.podcastPage.hlsUri}live/video_dev.${this.playerLive.conferenceId}/index.m3u8`;
|
|
47
|
+
//return "https://demo.unified-streaming.com/k8s/features/stable/video/tears-of-steel/tears-of-steel.ism/.m3u8";
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
|
|
51
|
+
methods: {
|
|
52
|
+
...mapActions(usePlayerStore, ["playerPlay",]),
|
|
53
|
+
closePlayer(){
|
|
54
|
+
this.playerPlay();
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
});
|
|
58
|
+
</script>
|
|
59
|
+
|
|
60
|
+
<style lang="scss">
|
|
61
|
+
.octopus-app {
|
|
62
|
+
.video-wrapper{
|
|
63
|
+
border-radius: 2rem;
|
|
64
|
+
overflow: hidden;
|
|
65
|
+
position: fixed;
|
|
66
|
+
bottom: 2.5rem;
|
|
67
|
+
right: 0;
|
|
68
|
+
z-index: 10;
|
|
69
|
+
}
|
|
70
|
+
.video-close{
|
|
71
|
+
position: fixed;
|
|
72
|
+
bottom: 16.5rem;
|
|
73
|
+
right: 1rem;
|
|
74
|
+
}
|
|
75
|
+
@media (max-width: 500px) {
|
|
76
|
+
.video-wrapper{
|
|
77
|
+
position:relative;
|
|
78
|
+
padding-bottom:56.25%;
|
|
79
|
+
height:0;
|
|
80
|
+
}
|
|
81
|
+
.video-wrapper iframe {
|
|
82
|
+
position:absolute;
|
|
83
|
+
top:0;
|
|
84
|
+
left:0;
|
|
85
|
+
width:100% !important;
|
|
86
|
+
height:100%;
|
|
87
|
+
margin:0 !important;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
</style>
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<iframe
|
|
3
|
+
ref="iframeVideo"
|
|
4
|
+
:src="srcVideo"
|
|
5
|
+
width="500"
|
|
6
|
+
height="281"
|
|
7
|
+
style="z-index:1;"
|
|
8
|
+
allowfullscreen="true"
|
|
9
|
+
allow="autoplay"
|
|
10
|
+
referrerpolicy="no-referrer-when-downgrade"
|
|
11
|
+
></iframe>
|
|
12
|
+
</template>
|
|
13
|
+
|
|
14
|
+
<script lang="ts">
|
|
15
|
+
import { usePlayerStore } from "@/stores/PlayerStore";
|
|
16
|
+
import { mapState } from "pinia";
|
|
17
|
+
import { defineComponent } from "vue";
|
|
18
|
+
export default defineComponent({
|
|
19
|
+
name: "PlayerVideo",
|
|
20
|
+
components: {
|
|
21
|
+
},
|
|
22
|
+
|
|
23
|
+
computed:{
|
|
24
|
+
...mapState(usePlayerStore, [
|
|
25
|
+
"playerPodcast",
|
|
26
|
+
"playerVideo"
|
|
27
|
+
]),
|
|
28
|
+
srcVideo(): string{
|
|
29
|
+
if(this.playerVideo){
|
|
30
|
+
return "//www.ultimedia.com/deliver/generic/iframe/mdtk/01009833/zone/1/showtitle/1/src/"+ this.playerPodcast?.video?.videoId+"/autoplay/1";
|
|
31
|
+
}
|
|
32
|
+
return "";
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
watch:{
|
|
36
|
+
srcVideo() {
|
|
37
|
+
this.goFullScreen();
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
mounted(){
|
|
41
|
+
this.goFullScreen();
|
|
42
|
+
},
|
|
43
|
+
methods:{
|
|
44
|
+
goFullScreen(){
|
|
45
|
+
if(""===this.srcVideo){return;}
|
|
46
|
+
switch (screen.orientation.type) {
|
|
47
|
+
case "landscape-primary":
|
|
48
|
+
case "landscape-secondary":
|
|
49
|
+
(this.$refs.iframeVideo as Element).requestFullscreen();
|
|
50
|
+
break;
|
|
51
|
+
case "portrait-secondary":
|
|
52
|
+
case "portrait-primary":
|
|
53
|
+
console.log("Portrait mode");
|
|
54
|
+
break;
|
|
55
|
+
default:
|
|
56
|
+
console.log("The orientation API isn't supported in this browser :(");
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
});
|
|
62
|
+
</script>
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="video-player">
|
|
3
|
+
<div v-if="errorPlay.length" class="video-live-error">{{errorPlay}}</div>
|
|
4
|
+
<video
|
|
5
|
+
v-show="useVideoSrc"
|
|
6
|
+
ref="videoelement"
|
|
7
|
+
playsinline
|
|
8
|
+
/>
|
|
9
|
+
<div
|
|
10
|
+
ref="videocontainer"
|
|
11
|
+
class="video-container"
|
|
12
|
+
/>
|
|
13
|
+
</div>
|
|
14
|
+
</template>
|
|
15
|
+
<script lang="ts">
|
|
16
|
+
|
|
17
|
+
// @ts-ignore
|
|
18
|
+
import Clappr from '@clappr/core';
|
|
19
|
+
// @ts-ignore
|
|
20
|
+
import HlsjsPlayback from '@clappr/hlsjs-playback';
|
|
21
|
+
import { defineComponent } from 'vue';
|
|
22
|
+
export default defineComponent({
|
|
23
|
+
name: "PlayerVideoHls",
|
|
24
|
+
|
|
25
|
+
props: {
|
|
26
|
+
hlsUrl: { default: "", type: String },
|
|
27
|
+
},
|
|
28
|
+
|
|
29
|
+
emits:['changeValid'],
|
|
30
|
+
data() {
|
|
31
|
+
return {
|
|
32
|
+
errorPlay: "" as string,
|
|
33
|
+
useVideoSrc: false as boolean,
|
|
34
|
+
player: undefined as Clappr.Player,
|
|
35
|
+
playing: false as boolean,
|
|
36
|
+
stalledTimout: undefined as ReturnType<typeof setTimeout>|undefined,
|
|
37
|
+
};
|
|
38
|
+
},
|
|
39
|
+
computed:{
|
|
40
|
+
videoContainer(): HTMLElement{
|
|
41
|
+
return (this.$refs.videocontainer as HTMLElement);
|
|
42
|
+
},
|
|
43
|
+
videoElement(): HTMLVideoElement{
|
|
44
|
+
return (this.$refs.videoelement as HTMLVideoElement);
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
mounted(){
|
|
48
|
+
this.playLive();
|
|
49
|
+
},
|
|
50
|
+
|
|
51
|
+
beforeUnmount() {
|
|
52
|
+
if(this.playing){
|
|
53
|
+
this.stopLive();
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
|
|
57
|
+
methods: {
|
|
58
|
+
definedStalledTimeout(){
|
|
59
|
+
this.stalledTimout =setTimeout(()=>{
|
|
60
|
+
this.videoClean();
|
|
61
|
+
this.playLive();
|
|
62
|
+
}, 5000);
|
|
63
|
+
},
|
|
64
|
+
async playLive(): Promise<void> {
|
|
65
|
+
clearTimeout(this.stalledTimout);
|
|
66
|
+
this.definedStalledTimeout();
|
|
67
|
+
if (this.videoElement.canPlayType('application/vnd.apple.mpegurl') && !navigator.userAgent.includes('Android')) {
|
|
68
|
+
this.useVideoSrc = true;
|
|
69
|
+
this.playLiveIos();
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
this.player = new Clappr.Player({
|
|
73
|
+
source: this.hlsUrl,
|
|
74
|
+
autoPlay: false,
|
|
75
|
+
height: '100%',
|
|
76
|
+
width: '100%',
|
|
77
|
+
plugins: {
|
|
78
|
+
playback: [HlsjsPlayback],
|
|
79
|
+
},
|
|
80
|
+
playback: {
|
|
81
|
+
controls: true,
|
|
82
|
+
playInline: true,
|
|
83
|
+
hlsjsConfig: {
|
|
84
|
+
enableWorker: false,
|
|
85
|
+
debug:true,
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
events: {
|
|
89
|
+
onError: async(error: Clappr.error) =>{
|
|
90
|
+
this.stopLive();
|
|
91
|
+
if (error.description && error.description.includes('403')) {
|
|
92
|
+
this.errorPlay = this.$t('Video is unavailable');
|
|
93
|
+
}else{
|
|
94
|
+
this.errorPlay = this.$t('Podcast play error');
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
onPlay:()=>{
|
|
98
|
+
this.errorPlay = "";
|
|
99
|
+
this.playing = true;
|
|
100
|
+
},
|
|
101
|
+
onTimeUpdate:()=>{
|
|
102
|
+
clearTimeout(this.stalledTimout);
|
|
103
|
+
this.definedStalledTimeout();
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
this.playing = true;
|
|
108
|
+
this.player.attachTo(this.videoContainer);
|
|
109
|
+
if(0!==this.videoContainer.getElementsByTagName("video").length){
|
|
110
|
+
this.videoContainer.getElementsByTagName("video")[0].play();
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
async playLiveIos(): Promise<void>{
|
|
114
|
+
this.videoElement.onloadedmetadata = ()=>{
|
|
115
|
+
const playPromise = this.videoElement.play();
|
|
116
|
+
if (playPromise !== undefined) {
|
|
117
|
+
playPromise.then(() => {
|
|
118
|
+
this.errorPlay = "";
|
|
119
|
+
this.playing = true;
|
|
120
|
+
})
|
|
121
|
+
.catch(() => {
|
|
122
|
+
this.playing = false;
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
this.videoElement.onerror = async()=>{
|
|
127
|
+
this.stopLive();
|
|
128
|
+
this.errorPlay = this.$t('Podcast play error');
|
|
129
|
+
};
|
|
130
|
+
this.videoElement.ontimeupdate = async()=>{
|
|
131
|
+
clearTimeout(this.stalledTimout);
|
|
132
|
+
this.definedStalledTimeout();
|
|
133
|
+
};
|
|
134
|
+
this.videoElement.src = this.hlsUrl;
|
|
135
|
+
},
|
|
136
|
+
videoClean(): void{
|
|
137
|
+
if(this.useVideoSrc){
|
|
138
|
+
this.videoElement.pause();
|
|
139
|
+
this.videoElement.removeAttribute('src');
|
|
140
|
+
this.videoElement.load();
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
this.player.destroy();
|
|
144
|
+
},
|
|
145
|
+
stopLive(): void{
|
|
146
|
+
clearTimeout(this.stalledTimout);
|
|
147
|
+
this.errorPlay = "";
|
|
148
|
+
this.videoClean();
|
|
149
|
+
this.playing = false;
|
|
150
|
+
},
|
|
151
|
+
},
|
|
152
|
+
|
|
153
|
+
});
|
|
154
|
+
</script>
|
|
155
|
+
|
|
156
|
+
<style lang="scss">
|
|
157
|
+
@import "@scss/_variables.scss";
|
|
158
|
+
.octopus-app{
|
|
159
|
+
.video-live-error{
|
|
160
|
+
text-align: center;
|
|
161
|
+
width: 100%;
|
|
162
|
+
font-size: 1rem;
|
|
163
|
+
font-weight: bold;
|
|
164
|
+
padding: 0.2rem 0;
|
|
165
|
+
color: white;
|
|
166
|
+
position: absolute;
|
|
167
|
+
top: 0;
|
|
168
|
+
background: $danger;
|
|
169
|
+
z-index: 1;
|
|
170
|
+
}
|
|
171
|
+
.video-container{
|
|
172
|
+
width: 500px;
|
|
173
|
+
height: 281px;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
</style>
|
package/src/locale/de.ts
CHANGED
package/src/locale/en.ts
CHANGED
package/src/locale/es.ts
CHANGED
package/src/locale/fr.ts
CHANGED
package/src/locale/it.ts
CHANGED
package/src/locale/sl.ts
CHANGED
|
@@ -21,6 +21,7 @@ interface PlayerState {
|
|
|
21
21
|
playerSeekTime?: number;
|
|
22
22
|
playerTranscript?: Transcript;
|
|
23
23
|
playerLargeVersion: boolean;
|
|
24
|
+
playerVideo: boolean;
|
|
24
25
|
}
|
|
25
26
|
export const usePlayerStore = defineStore("PlayerStore", {
|
|
26
27
|
state: (): PlayerState => ({
|
|
@@ -34,10 +35,12 @@ export const usePlayerStore = defineStore("PlayerStore", {
|
|
|
34
35
|
playerRadio: undefined,
|
|
35
36
|
playerSeekTime: 0,
|
|
36
37
|
playerLargeVersion: false,
|
|
38
|
+
playerVideo: false,
|
|
37
39
|
}),
|
|
38
40
|
getters: {
|
|
39
41
|
playerHeight() {
|
|
40
42
|
if ("STOPPED" === this.playerStatus) return 0;
|
|
43
|
+
if (this.playerVideo) return "0px"/* "281px" */;
|
|
41
44
|
if (this.playerLargeVersion) return "27rem";
|
|
42
45
|
if (window.innerWidth > 450) return "5rem";
|
|
43
46
|
return "3.5rem";
|
|
@@ -88,7 +91,7 @@ export const usePlayerStore = defineStore("PlayerStore", {
|
|
|
88
91
|
},
|
|
89
92
|
},
|
|
90
93
|
actions: {
|
|
91
|
-
playerPlay(param?: any) {
|
|
94
|
+
playerPlay(param?: any, isVideo = false) {
|
|
92
95
|
if (!param) {
|
|
93
96
|
this.playerStatus = "STOPPED";
|
|
94
97
|
this.playerPodcast = undefined;
|
|
@@ -96,13 +99,14 @@ export const usePlayerStore = defineStore("PlayerStore", {
|
|
|
96
99
|
this.playerLive = undefined;
|
|
97
100
|
this.playerRadio = undefined;
|
|
98
101
|
this.playerElapsed = 0;
|
|
102
|
+
this.playerVideo = false;
|
|
99
103
|
return;
|
|
100
104
|
}
|
|
101
105
|
if (
|
|
102
106
|
(this.playerPodcast &&
|
|
103
|
-
this.playerPodcast.podcastId === param.podcastId) ||
|
|
107
|
+
this.playerPodcast.podcastId === param.podcastId && isVideo === this.playerVideo) ||
|
|
104
108
|
(this.playerMedia && this.playerMedia.mediaId === param.mediaId) ||
|
|
105
|
-
(this.playerLive && this.playerLive.conferenceId === param.conferenceId)
|
|
109
|
+
(this.playerLive && this.playerLive.conferenceId === param.conferenceId && isVideo === this.playerVideo)
|
|
106
110
|
) {
|
|
107
111
|
//Do nothing
|
|
108
112
|
return;
|
|
@@ -112,6 +116,7 @@ export const usePlayerStore = defineStore("PlayerStore", {
|
|
|
112
116
|
this.playerMedia = undefined;
|
|
113
117
|
this.playerLive = undefined;
|
|
114
118
|
this.playerRadio = undefined;
|
|
119
|
+
this.playerVideo = isVideo;
|
|
115
120
|
this.playerElapsed = 0;
|
|
116
121
|
if (
|
|
117
122
|
param.conferenceId &&
|
|
@@ -2,6 +2,7 @@ import { Emission, emptyEmissionData } from "./emission";
|
|
|
2
2
|
import { Organisation } from "./organisation";
|
|
3
3
|
import { Participant } from "./participant";
|
|
4
4
|
import { Person } from "../user/person";
|
|
5
|
+
import { Video } from "./video";
|
|
5
6
|
export interface Podcast {
|
|
6
7
|
imageUrl?: string;
|
|
7
8
|
animators?: Array<Participant>;
|
|
@@ -39,7 +40,9 @@ export interface Podcast {
|
|
|
39
40
|
title: string;
|
|
40
41
|
weekDownloadCount?: number;
|
|
41
42
|
order?: number;
|
|
43
|
+
video?: Video;
|
|
42
44
|
}
|
|
45
|
+
|
|
43
46
|
export function emptyPodcastData(): Podcast {
|
|
44
47
|
return {
|
|
45
48
|
podcastId: 0,
|