eyevinn-channel-engine 3.1.0 → 3.1.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/engine/session.js CHANGED
@@ -395,20 +395,10 @@ class Session {
395
395
  if (!this._sessionState) {
396
396
  throw new Error('Session not ready');
397
397
  }
398
- const sessionState = await this._sessionState.getValues(["discSeq", "vodMediaSeqVideo"]);
398
+ const sessionState = await this._sessionState.getValues(["discSeq"]);
399
399
  const playheadState = await this._playheadState.getValues(["mediaSeq", "vodMediaSeqVideo"]);
400
400
 
401
- /*
402
- Since sessionState is always newer. If it is a smaller value, then this signals that
403
- a new vod has been loaded but playheadState has yet to get the new mseq value in 'incrementAsync()'.
404
- Without this, we risk returning an m3u8 with an old mseq on a new vod to the client.
405
- */
406
- if (playheadState.vodMediaSeqVideo > sessionState.vodMediaSeqVideo) {
407
- playheadState.vodMediaSeqVideo = sessionState.vodMediaSeqVideo;
408
- }
409
-
410
- if (playheadState.vodMediaSeqVideo === 0 || this.waitingForNextVod) {
411
- this.waitingForNextVod = false;
401
+ if (playheadState.vodMediaSeqVideo === 0) {
412
402
  const isLeader = await this._sessionStateStore.isLeader(this._instanceId);
413
403
  if (!isLeader) {
414
404
  debug(`[${this._sessionId}]: Not a leader and first media sequence in a VOD is requested. Invalidate cache to ensure having the correct VOD.`);
@@ -465,14 +455,6 @@ class Session {
465
455
  let sessionState = await this._sessionState.getValues(
466
456
  ["state", "mediaSeq", "discSeq", "vodMediaSeqVideo", "vodMediaSeqAudio"]);
467
457
  let playheadState = await this._playheadState.getValues(["mediaSeq", "vodMediaSeqVideo", "vodMediaSeqAudio"]);
468
- if (playheadState.vodMediaSeqVideo < 2) {
469
- // This is due to the possibility that we miss the tick where vodMediaSeqVideo is 0
470
- // The worst case scenario is that we clear cache two times in a row on a switch
471
- if (!isLeader) {
472
- debug(`[${this._sessionId}]: Not a leader and first media sequence in a VOD is requested. Invalidate cache to ensure having the correct VOD.`);
473
- await this._sessionState.clearCurrentVodCache(); // force reading up from shared store
474
- }
475
- }
476
458
  let currentVod = await this._sessionState.getCurrentVod();
477
459
  if (!currentVod ||
478
460
  sessionState.vodMediaSeqVideo === null ||
@@ -517,6 +499,12 @@ class Session {
517
499
  debug(`[${this._sessionId}]: INCREMENT (mseq=${playheadState.mediaSeq + playheadState.vodMediaSeqVideo}) vodMediaSeq=(${playheadState.vodMediaSeqVideo}_${playheadState.vodMediaSeqAudio} of ${currentVod.getLiveMediaSequencesCount()})`);
518
500
  let m3u8 = currentVod.getLiveMediaSequences(playheadState.mediaSeq, 180000, playheadState.vodMediaSeqVideo, sessionState.discSeq);
519
501
  await this._playheadState.setLastM3u8(m3u8);
502
+
503
+ if (!isLeader && playheadState.vodMediaSeqVideo < 2) {
504
+ debug(`[${this._sessionId}]: Not a leader and have just set playheadState vodMediaSeqVideo to 0|1. Invalidate cache to ensure having the correct VOD.`);
505
+ await this._sessionState.clearCurrentVodCache();
506
+ }
507
+
520
508
  return m3u8;
521
509
  }
522
510
 
@@ -18,6 +18,7 @@ const daterangeAttribute = (key, attr) => {
18
18
  const TARGET_PLAYLIST_DURATION_SEC = 60;
19
19
  const RESET_DELAY = 5000;
20
20
  const FAIL_TIMEOUT = 4000;
21
+ const DEFAULT_PLAYHEAD_INTERVAL_MS = 6 * 1000;
21
22
  const PlayheadState = Object.freeze({
22
23
  RUNNING: 1,
23
24
  STOPPED: 2,
@@ -40,7 +41,6 @@ class SessionLive {
40
41
  this.mediaManifestURIs = {};
41
42
  this.liveSegQueue = {};
42
43
  this.lastRequestedMediaSeqRaw = null;
43
- this.targetNumSeg = 0;
44
44
  this.liveSourceM3Us = {};
45
45
  this.playheadState = PlayheadState.IDLE;
46
46
  this.liveSegsForFollowers = {};
@@ -117,7 +117,6 @@ class SessionLive {
117
117
  this.mediaManifestURIs = {};
118
118
  this.liveSegQueue = {};
119
119
  this.lastRequestedMediaSeqRaw = null;
120
- this.targetNumSeg = 0;
121
120
  this.liveSourceM3Us = {};
122
121
  this.liveSegsForFollowers = {};
123
122
  this.timerCompensation = null;
@@ -149,13 +148,6 @@ class SessionLive {
149
148
  return;
150
149
  }
151
150
 
152
- // Let the playhead move at an interval set according to live segment duration
153
- let liveSegmentDurationMs = 6000;
154
- let liveBws = Object.keys(this.liveSegQueue);
155
- if (liveBws.length !== 0 && this.liveSegQueue[liveBws[0]].length !== 0 && this.liveSegQueue[liveBws[0]][0].duration) {
156
- liveSegmentDurationMs = this.liveSegQueue[liveBws[0]][0].duration * 1000;
157
- }
158
-
159
151
  // Fetch Live-Source Segments, and get ready for on-the-fly manifest generation
160
152
  // And also compensate for processing time
161
153
 
@@ -165,6 +157,13 @@ class SessionLive {
165
157
  const tsIncrementEnd = Date.now();
166
158
  this.waitForPlayhead = false;
167
159
 
160
+ // Let the playhead move at an interval set according to live segment duration
161
+ let liveSegmentDurationMs = DEFAULT_PLAYHEAD_INTERVAL_MS;
162
+ let liveBws = Object.keys(this.liveSegQueue);
163
+ if (liveBws.length !== 0 && this.liveSegQueue[liveBws[0]].length !== 0 && this.liveSegQueue[liveBws[0]][0].duration) {
164
+ liveSegmentDurationMs = this.liveSegQueue[liveBws[0]][0].duration * 1000;
165
+ }
166
+
168
167
  // Set the timer
169
168
  let timerValueMs = 0;
170
169
  if (this.timerCompensation) {
@@ -242,14 +241,13 @@ class SessionLive {
242
241
  }
243
242
  // Make it possible to add & share new segments
244
243
  this.allowedToSet = true;
245
- let segCount = 0;
246
244
  const allBws = Object.keys(segments);
247
245
  for (let i = 0; i < allBws.length; i++) {
248
246
  const bw = allBws[i];
249
247
  if (!this.vodSegments[bw]) {
250
248
  this.vodSegments[bw] = [];
251
249
  }
252
-
250
+
253
251
  if (segments[bw][0].discontinuity) {
254
252
  segments[bw].shift();
255
253
  }
@@ -264,12 +262,6 @@ class SessionLive {
264
262
  }
265
263
  }
266
264
 
267
- for (let segIdx = 0; segIdx < segments[allBws[0]].length; segIdx++) {
268
- if (segments[allBws[0]][segIdx].uri) {
269
- segCount++;
270
- }
271
- }
272
- this.targetNumSeg = segCount;
273
265
  debug(`[${this.sessionId}]: Setting CurrentMediaSequenceSegments. First seg is: [${this.vodSegments[allBws[0]][0].uri}]`);
274
266
 
275
267
  const isLeader = await this.sessionLiveStateStore.isLeader(this.instanceId);
@@ -645,12 +637,16 @@ class SessionLive {
645
637
  if (Object.keys(this.liveSegQueue).length > 0) {
646
638
  const firstBw = Object.keys(this.liveSegQueue)[0];
647
639
  const lastIdx = this.liveSegQueue[firstBw].length - 1;
648
- retryDelayMs = this.liveSegQueue[firstBw][lastIdx].duration * 1000 * 0.25;
640
+ if (this.liveSegQueue[firstBw][lastIdx].duration) {
641
+ retryDelayMs = this.liveSegQueue[firstBw][lastIdx].duration * 1000 * 0.25;
642
+ }
649
643
  }
650
644
  // Wait a little before trying again
651
645
  debug(`[${this.sessionId}]: ALERT! Live Source Data NOT in sync! Will try again after ${retryDelayMs}ms`);
652
646
  await timer(retryDelayMs);
653
- this.timerCompensation = false;
647
+ if (isLeader) {
648
+ this.timerCompensation = false;
649
+ }
654
650
  continue;
655
651
  }
656
652
 
@@ -688,14 +684,6 @@ class SessionLive {
688
684
  const transitSegs = await this.sessionLiveState.get("transitSegs");
689
685
  if (!this._isEmpty(transitSegs)) {
690
686
  this.vodSegments = transitSegs;
691
- let discTagCount = 0;
692
- const allBws = Object.keys(this.vodSegments);
693
- for (let segIdx = 0; segIdx < this.vodSegments[allBws[0]].length; segIdx++) {
694
- if (this.vodSegments[allBws[0]][segIdx].discontinuity) {
695
- discTagCount++;
696
- }
697
- }
698
- this.targetNumSeg = this.vodSegments[allBws[0]].length - (discTagCount - 1);
699
687
  }
700
688
  }
701
689
 
@@ -711,14 +699,6 @@ class SessionLive {
711
699
  //debug(`[${this.sessionId}]: NEW FOLLOWER: I tried to get 'transitSegs'. This is what I found ${JSON.stringify(transitSegs)}`);
712
700
  if (!this._isEmpty(transitSegs)) {
713
701
  this.vodSegments = transitSegs;
714
- let discTagCount = 0;
715
- const allBws = Object.keys(this.vodSegments);
716
- for (let segIdx = 0; segIdx < this.vodSegments[allBws[0]].length; segIdx++) {
717
- if (this.vodSegments[allBws[0]][segIdx].discontinuity) {
718
- discTagCount++;
719
- }
720
- }
721
- this.targetNumSeg = this.vodSegments[allBws[0]].length - (discTagCount - 1);
722
702
  }
723
703
  }
724
704
  debug(`[${this.sessionId}]: ...pushAmount=${this.pushAmount}`);
@@ -779,7 +759,8 @@ class SessionLive {
779
759
  await allSettled(pushPromises);
780
760
 
781
761
  // UPDATE COUNTS, & Shift Segments in vodSegments and liveSegQueue if needed.
782
- const newTotalDuration = this._incrementAndShift("LEADER");
762
+ const leaderORFollower = isLeader ? "LEADER" : "NEW FOLLOWER";
763
+ const newTotalDuration = this._incrementAndShift(leaderORFollower);
783
764
  if (newTotalDuration) {
784
765
  debug(`[${this.sessionId}]: New Adjusted Playlist Duration=${newTotalDuration}s`);
785
766
  }
@@ -1128,7 +1109,7 @@ class SessionLive {
1128
1109
  }
1129
1110
  // Push new Live Segments!
1130
1111
  this.liveSegQueue[liveTargetBandwidth].push(seg);
1131
- this.liveSegsForFollowers[liveTargetBandwidth].push(seg);
1112
+ this.liveSegsForFollowers[liveTargetBandwidth].push(seg);
1132
1113
  }
1133
1114
  }
1134
1115
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eyevinn-channel-engine",
3
- "version": "3.1.0",
3
+ "version": "3.1.3",
4
4
  "description": "OTT TV Channel Engine",
5
5
  "main": "index.js",
6
6
  "scripts": {