@saooti/octopus-sdk 34.0.2 → 34.0.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@saooti/octopus-sdk",
3
- "version": "34.0.2",
3
+ "version": "34.0.3",
4
4
  "private": false,
5
5
  "description": "Javascript SDK for using octopus",
6
6
  "author": "Saooti",
@@ -16,7 +16,7 @@
16
16
  "test": "jest --coverage"
17
17
  },
18
18
  "dependencies": {
19
- "@saooti/octopus-api": "^0.33.0",
19
+ "@saooti/octopus-api": "^0.34.0",
20
20
  "@vue/cli": "^5.0.8",
21
21
  "@vue/compat": "^3.2.45",
22
22
  "autoprefixer": "^10.4.13",
@@ -7,7 +7,7 @@
7
7
  <template v-if="display">
8
8
  <audio
9
9
  id="audio-player"
10
- :src="!live? audioUrlToPlay: undefined"
10
+ :src="!live && !radio? audioUrlToPlay: undefined"
11
11
  autoplay
12
12
  @timeupdate="onTimeUpdate"
13
13
  @ended="onFinished"
@@ -31,7 +31,10 @@
31
31
  />
32
32
  </button>
33
33
  <div class="text-light player-grow-content">
34
- <div class="d-flex mb-1">
34
+ <div
35
+ class="d-flex"
36
+ :class="!radio?'mb-1':''"
37
+ >
35
38
  <div
36
39
  v-if="playerError"
37
40
  class="text-warning mx-2"
@@ -42,13 +45,14 @@
42
45
  {{ podcastTitle }}
43
46
  </div>
44
47
  <div
45
- v-if="!playerError"
48
+ v-if="!playerError && !radio"
46
49
  class="hide-phone"
47
50
  >
48
51
  {{ playedTime }} / {{ totalTime }}
49
52
  </div>
50
53
  </div>
51
54
  <PlayerProgressBar
55
+ v-if="!radio"
52
56
  :hls-ready="hlsReady"
53
57
  :show-timeline="showTimeline"
54
58
  :comments="comments"
@@ -61,6 +65,7 @@
61
65
  />
62
66
  </div>
63
67
  <button
68
+ v-if="!radio"
64
69
  :title="$t('Enlarge')"
65
70
  class="btn play-button-box btn-transparent text-light saooti-up"
66
71
  @click="changePlayerLargeVersion"
@@ -71,6 +76,7 @@
71
76
  @click="stopPlayer"
72
77
  />
73
78
  <PlayerTimeline
79
+ v-if="!radio"
74
80
  v-model:showTimeline="showTimeline"
75
81
  :comments="comments"
76
82
  />
@@ -3,9 +3,16 @@ import DurationHelper from '../../../helper/duration';
3
3
  import { state } from '../../../store/paramStore';
4
4
  import { defineComponent } from 'vue';
5
5
  import { RouteLocationRaw } from 'vue-router';
6
+ import { Radio } from '@/store/class/general/player';
7
+ import octopusApi from '@saooti/octopus-api';
6
8
  export const playerDisplay = defineComponent({
7
9
  props: {
8
10
  hlsReady: { default: false , type: Boolean},
11
+ },
12
+ data() {
13
+ return {
14
+ radioInterval: undefined as ReturnType<typeof setTimeout>|undefined,
15
+ };
9
16
  },
10
17
  computed:{
11
18
  playedTime(): string{
@@ -51,6 +58,9 @@ export const playerDisplay = defineComponent({
51
58
  return (state.player.emissionName as boolean);
52
59
  },
53
60
  podcastTitle(): string {
61
+ if(this.$store.state.player.radio){
62
+ return this.$store.state.player.radio.metadata;
63
+ }
54
64
  if (this.$store.state.player.podcast) {
55
65
  if (this.isEmissionName)
56
66
  return this.emissionName + ' - ' + this.$store.state.player.podcast.title;
@@ -70,16 +80,38 @@ export const playerDisplay = defineComponent({
70
80
  },
71
81
  transcriptText():string{
72
82
  return this.$store.state.player.transcript?.actualText ?? "";
83
+ },
84
+ radio(): Radio{
85
+ return this.$store.state.player.radio;
73
86
  }
74
87
  },
88
+ watch:{
89
+ radio: {
90
+ deep: true,
91
+ immediate:true,
92
+ handler(){
93
+ clearInterval((this.radioInterval as unknown as number));
94
+ if(this.radio){
95
+ this.fetchRadioMetadata();
96
+ this.radioInterval = setInterval(() => {
97
+ this.fetchRadioMetadata();
98
+ }, 2000);
99
+ }
100
+ }
101
+ },
102
+ },
75
103
  created(){
76
104
  window.addEventListener('keydown', this.addKeyboardControl);
77
105
  },
78
106
  beforeUnmount() {
79
107
  window.removeEventListener('keydown', this.addKeyboardControl);
108
+ clearInterval((this.radioInterval as unknown as number));
80
109
  },
81
-
82
110
  methods: {
111
+ async fetchRadioMetadata(): Promise<void>{
112
+ const metadata = await octopusApi.fetchData<string>(14, 'player/playing/'+this.$store.state.player.radio.canalId);
113
+ this.$store.commit('player/radioMetadata', metadata);
114
+ },
83
115
  addKeyboardControl(event: KeyboardEvent): void{
84
116
  if(!event || null ===event){return;}
85
117
  const element = event.target as HTMLElement;
@@ -26,18 +26,21 @@ export const playerLive = defineComponent({
26
26
  onPlay(): void {
27
27
  this.$store.commit('player/pause', false);
28
28
  },
29
- async playLive(): Promise<void> {
29
+ playRadio(){
30
+ if (!this.radio) return;
31
+ this.playHls(this.radio.url);
32
+ },
33
+ playLive() {
30
34
  if (!this.live) return;
31
- const hlsStreamUrl =
32
- state.podcastPage.hlsUri +
33
- 'stream/dev.' +
34
- this.live.conferenceId +
35
- '/index.m3u8';
35
+ const hlsStreamUrl = `${state.podcastPage.hlsUri}stream/dev.${this.live.conferenceId}/index.m3u8`;
36
+ this.playHls(hlsStreamUrl);
37
+ },
38
+ async playHls(hlsStreamUrl: string): Promise<void>{
36
39
  try {
37
40
  this.audioElement = (document.getElementById('audio-player') as HTMLAudioElement);
38
41
  if(null===this.audioElement){
39
42
  setTimeout(() => {
40
- this.playLive();
43
+ this.playHls(hlsStreamUrl);
41
44
  }, 1000);
42
45
  return;
43
46
  }
@@ -51,7 +54,7 @@ export const playerLive = defineComponent({
51
54
  }
52
55
  } catch (error) {
53
56
  setTimeout(() => {
54
- this.playLive();
57
+ this.playHls(hlsStreamUrl);
55
58
  }, 1000);
56
59
  }
57
60
  },
@@ -4,11 +4,11 @@ import { CommentPodcast } from '@/store/class/general/comment';
4
4
  import cookies from '../cookies';
5
5
  import { playerLive } from './playerLive';
6
6
  import { playerComment } from './playerComment';
7
+ import { playerTranscript } from './playerTranscript';
7
8
  import { defineComponent } from 'vue';
8
9
  import { Player } from '@/store/class/general/player';
9
- import { StoreState } from '@/store/classStore/typeAppStore';
10
10
  export const playerLogic = defineComponent({
11
- mixins:[cookies,playerLive,playerComment],
11
+ mixins:[cookies,playerLive,playerComment, playerTranscript],
12
12
  data() {
13
13
  return {
14
14
  forceHide: false as boolean,
@@ -32,16 +32,15 @@ export const playerLogic = defineComponent({
32
32
  podcast (state: Player){ return state.podcast},
33
33
  media: (state: Player) => state.media,
34
34
  live: (state: Player) => state.live,
35
+ radio: (state: Player) => state.radio,
35
36
  volume: (state: Player) => state.volume,
37
+ status : (state: Player) => state.status,
36
38
  percentProgress: (state: Player) => {
37
39
  if(!state.elapsed){return 0;}
38
40
  return state.elapsed * 100;
39
41
  },
40
42
  playerSeekTime: (state: Player) => state.seekTime,
41
43
  }),
42
- commentsLoaded(){
43
- return this.$store.state.comments.loadedComments;
44
- },
45
44
  audioUrl(): string {
46
45
  return this.getAudioUrl();
47
46
  },
@@ -71,12 +70,19 @@ export const playerLogic = defineComponent({
71
70
  this.$nextTick(async () => {
72
71
  this.hlsReady = false;
73
72
  this.reInitPlayer();
74
- await this.playLive();
73
+ this.playLive();
75
74
  });
76
75
  }
77
76
  },
77
+ radio(){
78
+ this.$nextTick(async () => {
79
+ this.hlsReady = false;
80
+ this.reInitPlayer();
81
+ this.playRadio();
82
+ });
83
+ },
78
84
  async listenTime(newVal): Promise<void> {
79
- if ((!this.podcast && !this.live)||(!this.downloadId)||(newVal - this.lastSend < 10)) {
85
+ if (this.radio && (!this.podcast && !this.live)||(!this.downloadId)||(newVal - this.lastSend < 10)) {
80
86
  return;
81
87
  }
82
88
  this.lastSend = newVal;
@@ -91,48 +97,34 @@ export const playerLogic = defineComponent({
91
97
  if (!audioPlayer) return;
92
98
  audioPlayer.currentTime = this.playerSeekTime;
93
99
  },
100
+ status() {
101
+ const audioPlayer: HTMLAudioElement | null = document.querySelector('#audio-player');
102
+ if (!audioPlayer) return;
103
+ if (this.live && !this.hlsReady) {
104
+ audioPlayer.pause();
105
+ this.percentLiveProgress = 0;
106
+ this.durationLivePosition = 0;
107
+ return;
108
+ }
109
+ if ('PAUSED' === this.status && this.radio) {
110
+ this.hlsReady = false;
111
+ this.reInitPlayer();
112
+ this.endingLive();
113
+ }else if('PAUSED' === this.status){
114
+ audioPlayer.pause();
115
+ }else if ('PLAYING' === this.status && this.radio){
116
+ this.playRadio();
117
+ }else if('PLAYING' === this.status){
118
+ audioPlayer.play();
119
+ }
120
+ },
94
121
  },
95
122
 
96
123
  mounted() {
97
124
  window.addEventListener('beforeunload', this.endListeningProgress);
98
- this.watchPlayerStatus();
99
125
  },
100
126
 
101
127
  methods: {
102
- async getTranscription(): Promise<void>{
103
- if(!this.podcast){
104
- this.$store.commit('player/transcript',undefined);
105
- return;
106
- }
107
- const result = await octopusApi.fetchDataPublic<string>(11 , `response/${this.podcast.podcastId}`);
108
- const arrayTranscript = this.parseSrt(result);
109
- const actualText = arrayTranscript?.[0]?.startTime === 0 ? arrayTranscript[0].text : "";
110
- this.$store.commit('player/transcript',{actual: 0,actualText:actualText, value : arrayTranscript});
111
- },
112
- parseSrt(transcript: string){
113
- const pattern = /(\d+)\n([\d:,]+)\s+-{2}\>\s+([\d:,]+)\n([\s\S]*?(?=\n{2}|$))/gm;
114
- const result = [];
115
- if (typeof(transcript) != 'string'){
116
- return;
117
- }
118
- if (transcript == null){
119
- return;
120
- }
121
- transcript = transcript.replace(/\r\n|\r|\n|\t/g, '\n');
122
- let matches;
123
- while ((matches = pattern.exec(transcript)) != null) {
124
- result.push({
125
- startTime: this.srtTimeToSeconds(matches[2]),
126
- endTime: this.srtTimeToSeconds(matches[3]),
127
- text: matches[4]
128
- });
129
- }
130
- return result;
131
- },
132
- srtTimeToSeconds(time:string): number{
133
- const a = time.split(':');
134
- return (+a[0]) * 60 * 60 + (+a[1]) * 60 + (+parseFloat(a[2]));
135
- },
136
128
  getDomain(): string{
137
129
  let domain = "";
138
130
  const domainArray: RegExpExecArray | null = /\.(.+)/.exec(window.location.host);
@@ -183,26 +175,6 @@ export const playerLogic = defineComponent({
183
175
  }
184
176
  return listenerId;
185
177
  },
186
- watchPlayerStatus(): void {
187
- this.$store.watch(
188
- (state: StoreState) => state.player.status,
189
- (newValue: string) => {
190
- const audioPlayer: HTMLAudioElement | null = document.querySelector('#audio-player');
191
- if (!audioPlayer) return;
192
- if (this.live && !this.hlsReady) {
193
- audioPlayer.pause();
194
- this.percentLiveProgress = 0;
195
- this.durationLivePosition = 0;
196
- return;
197
- }
198
- if ('PAUSED' === newValue) {
199
- audioPlayer.pause();
200
- }else if ('PLAYING' === newValue){
201
- audioPlayer.play();
202
- }
203
- }
204
- );
205
- },
206
178
  onError(): void {
207
179
  if (this.podcast && ""!==this.audioUrlToPlay && !this.listenError) {
208
180
  this.listenError = true;
@@ -222,12 +194,7 @@ export const playerLogic = defineComponent({
222
194
  }
223
195
  return streamDuration;
224
196
  },
225
- onTimeUpdateTranscript(currentTime:number){
226
- if((this.$store.state.player.transcript?.value[this.$store.state.player.transcript?.actual]?.endTime ?? Infinity) < currentTime){
227
- this.$store.state.player.transcript.actual +=1;
228
- this.$store.state.player.transcript.actualText = this.$store.state.player.transcript?.value[this.$store.state.player.transcript?.actual].text ?? "";
229
- }
230
- },
197
+
231
198
  onTimeUpdatePodcast(streamDuration:number, currentTime:number){
232
199
  this.displayAlertBar = false;
233
200
  this.percentLiveProgress = 100;
@@ -284,23 +251,20 @@ export const playerLogic = defineComponent({
284
251
  onSeeked(event: Event):void {
285
252
  const mediaTarget = (event.currentTarget as HTMLMediaElement);
286
253
  const currentTime = mediaTarget.currentTime;
287
- if(this.$store.state.player.transcript){
288
- let newActual = 0;
289
- while (currentTime > (this.$store.state.player.transcript.value[newActual]?.endTime ?? Infinity)){
290
- newActual +=1;
291
- }
292
- this.$store.state.player.transcript.actual = newActual;
293
- }
254
+ this.onSeekedTranscript(currentTime);
294
255
  },
295
256
  onFinished(): void {
296
257
  this.setDownloadId(null);
297
258
  if (this.live) {
298
- const audio: HTMLElement|null = document.getElementById('audio-player');
299
- if(audio){
300
- (audio as HTMLAudioElement).src = '';
301
- }
259
+ this.endingLive();
302
260
  }
303
261
  this.forceHide = true;
304
262
  },
263
+ endingLive():void{
264
+ const audio: HTMLElement|null = document.getElementById('audio-player');
265
+ if(audio){
266
+ (audio as HTMLAudioElement).src = '';
267
+ }
268
+ }
305
269
  },
306
270
  })
@@ -0,0 +1,55 @@
1
+ import octopusApi from '@saooti/octopus-api';
2
+ import { defineComponent } from 'vue';
3
+ export const playerTranscript = defineComponent({
4
+ methods: {
5
+ async getTranscription(): Promise<void>{
6
+ if(!this.podcast){
7
+ this.$store.commit('player/transcript',undefined);
8
+ return;
9
+ }
10
+ const result = await octopusApi.fetchDataPublic<string>(11 , `response/${this.podcast.podcastId}`);
11
+ const arrayTranscript = this.parseSrt(result);
12
+ const actualText = arrayTranscript?.[0]?.startTime === 0 ? arrayTranscript[0].text : "";
13
+ this.$store.commit('player/transcript',{actual: 0,actualText:actualText, value : arrayTranscript});
14
+ },
15
+ parseSrt(transcript: string){
16
+ const pattern = /(\d+)\n([\d:,]+)\s+-{2}\>\s+([\d:,]+)\n([\s\S]*?(?=\n{2}|$))/gm;
17
+ const result = [];
18
+ if (typeof(transcript) != 'string'){
19
+ return;
20
+ }
21
+ if (transcript == null){
22
+ return;
23
+ }
24
+ transcript = transcript.replace(/\r\n|\r|\n|\t/g, '\n');
25
+ let matches;
26
+ while ((matches = pattern.exec(transcript)) != null) {
27
+ result.push({
28
+ startTime: this.srtTimeToSeconds(matches[2]),
29
+ endTime: this.srtTimeToSeconds(matches[3]),
30
+ text: matches[4]
31
+ });
32
+ }
33
+ return result;
34
+ },
35
+ srtTimeToSeconds(time:string): number{
36
+ const a = time.split(':');
37
+ return (+a[0]) * 60 * 60 + (+a[1]) * 60 + (+parseFloat(a[2]));
38
+ },
39
+ onTimeUpdateTranscript(currentTime:number){
40
+ if((this.$store.state.player.transcript?.value[this.$store.state.player.transcript?.actual]?.endTime ?? Infinity) < currentTime){
41
+ this.$store.state.player.transcript.actual +=1;
42
+ this.$store.state.player.transcript.actualText = this.$store.state.player.transcript?.value[this.$store.state.player.transcript?.actual].text ?? "";
43
+ }
44
+ },
45
+ onSeekedTranscript(currentTime: number){
46
+ if(this.$store.state.player.transcript){
47
+ let newActual = 0;
48
+ while (currentTime > (this.$store.state.player.transcript.value[newActual]?.endTime ?? Infinity)){
49
+ newActual +=1;
50
+ }
51
+ this.$store.state.player.transcript.actual = newActual;
52
+ }
53
+ }
54
+ },
55
+ })
@@ -10,6 +10,7 @@ const mutations = <MutationTree<Player>>{
10
10
  state.podcast = undefined;
11
11
  state.media = undefined;
12
12
  state.live = undefined;
13
+ state.radio = undefined;
13
14
  state.elapsed = 0;
14
15
  return;
15
16
  }
@@ -27,6 +28,7 @@ const mutations = <MutationTree<Player>>{
27
28
  state.podcast = undefined;
28
29
  state.media = undefined;
29
30
  state.live = undefined;
31
+ state.radio = undefined;
30
32
  state.elapsed = 0;
31
33
  if (
32
34
  podcast.conferenceId &&
@@ -37,9 +39,16 @@ const mutations = <MutationTree<Player>>{
37
39
  state.podcast = podcast;
38
40
  } else if (podcast.mediaId) {
39
41
  state.media = podcast;
42
+ }else if(podcast.canalId){
43
+ state.radio = podcast;
40
44
  }
41
45
  },
42
46
 
47
+ radioMetadata(state, metadata){
48
+ if(!state.radio){return;}
49
+ state.radio.metadata = metadata;
50
+ },
51
+
43
52
  pause(state, pause) {
44
53
  if (pause) {
45
54
  state.status = 'PAUSED';
@@ -63,6 +72,7 @@ const mutations = <MutationTree<Player>>{
63
72
  seekTime(state, seekTime) {
64
73
  state.seekTime = seekTime;
65
74
  },
75
+
66
76
  transcript(state, transcript) {
67
77
  state.transcript = transcript;
68
78
  },
@@ -1,6 +1,13 @@
1
1
  import { Media } from "./media";
2
2
  import { Podcast } from "./podcast";
3
3
 
4
+ export interface Radio{
5
+ canalId: number;
6
+ url: string;
7
+ metadata: string;
8
+ }
9
+
10
+
4
11
  export interface Player{
5
12
  status: string; //STOPPED, LOADING, PLAYING, PAUSED
6
13
  podcast: Podcast|undefined;
@@ -9,6 +16,7 @@ export interface Player{
9
16
  total?: number;
10
17
  media: Media|undefined;
11
18
  live: Podcast|undefined;
19
+ radio: Radio|undefined;
12
20
  stop?: boolean;
13
21
  seekTime?: number;
14
22
  transcript?:{actual: number, actualText:string, value : Array<{endTime: number, startTime:number, text: string}>};
@@ -9,6 +9,7 @@ export function getDefaultPlayerState(): Player {
9
9
  total: 0,
10
10
  media: undefined,
11
11
  live: undefined,
12
+ radio: undefined,
12
13
  seekTime:0,
13
14
  };
14
15
  }
@@ -181,6 +181,7 @@ export interface OctopusApi{
181
181
  imageUrl?: string,
182
182
  studioUrl?: string,
183
183
  playerUrl?: string,
184
+ radioUrl?:string,
184
185
  speechToTextUrl?:string,
185
186
  recoUrl?:string,
186
187
  organisationId?: string,