eyevinn-channel-engine 3.3.5 → 3.3.8
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/Dockerfile +1 -1
- package/engine/session.js +14 -7
- package/engine/session_live.js +59 -24
- package/engine/stream_switcher.js +6 -6
- package/package.json +1 -1
package/Dockerfile
CHANGED
package/engine/session.js
CHANGED
|
@@ -512,7 +512,7 @@ class Session {
|
|
|
512
512
|
}
|
|
513
513
|
|
|
514
514
|
const sessionState = await this._sessionState.getValues(["vodMediaSeqVideo", "discSeq"]);
|
|
515
|
-
|
|
515
|
+
let playheadState = await this._playheadState.getValues(["mediaSeq", "vodMediaSeqVideo"]);
|
|
516
516
|
|
|
517
517
|
if (this.prevVodMediaSeq.video === null) {
|
|
518
518
|
this.prevVodMediaSeq.video = playheadState.vodMediaSeqVideo;
|
|
@@ -522,13 +522,20 @@ class Session {
|
|
|
522
522
|
}
|
|
523
523
|
|
|
524
524
|
if (playheadState.vodMediaSeqVideo > sessionState.vodMediaSeqVideo) {
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
525
|
+
const state = await this._sessionState.get("state");
|
|
526
|
+
if ([SessionState.VOD_RELOAD_INIT, SessionState.VOD_RELOAD_INITIATING].includes(state)) {
|
|
527
|
+
debug(`[${this._sessionId}]: Recently reloaded Vod. PlayheadState not up-to-date (${playheadState.vodMediaSeqVideo}_${sessionState.vodMediaSeqVideo}). Waiting 500ms before reading from store again`);
|
|
528
|
+
await timer(500);
|
|
529
|
+
playheadState = await this._playheadState.getValues(["mediaSeq", "vodMediaSeqVideo"]);
|
|
530
530
|
} else {
|
|
531
|
-
debug(`[${this._sessionId}]:
|
|
531
|
+
debug(`[${this._sessionId}]: Recently Loaded Next Vod. PlayheadState not up-to-date. Return the last generated m3u8`);
|
|
532
|
+
const m3u8 = await this._playheadState.getLastM3u8();
|
|
533
|
+
if (m3u8) {
|
|
534
|
+
this.prevVodMediaSeq.video = playheadState.vodMediaSeqVideo;
|
|
535
|
+
return m3u8;
|
|
536
|
+
} else {
|
|
537
|
+
debug(`[${this._sessionId}]: We don't have any previously generated m3u8`);
|
|
538
|
+
}
|
|
532
539
|
}
|
|
533
540
|
}
|
|
534
541
|
|
package/engine/session_live.js
CHANGED
|
@@ -85,7 +85,7 @@ class SessionLive {
|
|
|
85
85
|
if (resetDelay === null || resetDelay < 0) {
|
|
86
86
|
resetDelay = RESET_DELAY;
|
|
87
87
|
}
|
|
88
|
-
|
|
88
|
+
debug(`[${this.instanceId}][${this.sessionId}]: LEADER: Resetting SessionLive values in Store ${resetDelay === 0 ? "Immediately" : `after a delay=(${resetDelay}ms)`}`);
|
|
89
89
|
await timer(resetDelay);
|
|
90
90
|
await this.sessionLiveState.set("liveSegsForFollowers", null);
|
|
91
91
|
await this.sessionLiveState.set("lastRequestedMediaSeqRaw", null);
|
|
@@ -95,7 +95,7 @@ class SessionLive {
|
|
|
95
95
|
mediaSeqCount: null,
|
|
96
96
|
discSeqCount: null,
|
|
97
97
|
});
|
|
98
|
-
debug(`[${this.instanceId}][${this.sessionId}]: LEADER:
|
|
98
|
+
debug(`[${this.instanceId}][${this.sessionId}]: LEADER: SessionLive values in Store have now been reset!`);
|
|
99
99
|
}
|
|
100
100
|
|
|
101
101
|
async resetSession() {
|
|
@@ -562,6 +562,18 @@ class SessionLive {
|
|
|
562
562
|
let attempts = 10;
|
|
563
563
|
// CHECK AGAIN CASE 1: Store Empty
|
|
564
564
|
while (!leadersMediaSeqRaw && attempts > 0) {
|
|
565
|
+
if (!leadersMediaSeqRaw) {
|
|
566
|
+
isLeader = await this.sessionLiveStateStore.isLeader(this.instanceId);
|
|
567
|
+
if (isLeader) {
|
|
568
|
+
debug(`[${this.instanceId}]: I'm the new leader`);
|
|
569
|
+
return;
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
if (!this.allowedToSet) {
|
|
574
|
+
debug(`[${this.sessionId}]: We are about to switch away from LIVE. Abort fetching from Store`);
|
|
575
|
+
break;
|
|
576
|
+
}
|
|
565
577
|
const segDur = this._getAnyFirstSegmentDurationMs() || DEFAULT_PLAYHEAD_INTERVAL_MS;
|
|
566
578
|
const waitTimeMs = parseInt(segDur / 3, 10);
|
|
567
579
|
debug(`[${this.sessionId}]: FOLLOWER: Leader has not put anything in store... Will check again in ${waitTimeMs}ms (Tries left=[${attempts}])`);
|
|
@@ -572,42 +584,45 @@ class SessionLive {
|
|
|
572
584
|
}
|
|
573
585
|
|
|
574
586
|
if (!leadersMediaSeqRaw) {
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
debug(`[${this.instanceId}]: I'm the new leader`);
|
|
578
|
-
return;
|
|
579
|
-
} else {
|
|
580
|
-
debug(`[${this.instanceId}]: The leader is still alive`);
|
|
581
|
-
return;
|
|
582
|
-
}
|
|
587
|
+
debug(`[${this.instanceId}]: The leader is still alive`);
|
|
588
|
+
return;
|
|
583
589
|
}
|
|
584
590
|
|
|
591
|
+
let liveSegsInStore = await this.sessionLiveState.get("liveSegsForFollowers");
|
|
585
592
|
attempts = 10;
|
|
586
593
|
// CHECK AGAIN CASE 2: Store Old
|
|
587
|
-
while (leadersMediaSeqRaw <= this.lastRequestedMediaSeqRaw && attempts > 0) {
|
|
594
|
+
while ((leadersMediaSeqRaw <= this.lastRequestedMediaSeqRaw && attempts > 0) || (this._containsSegment(this.liveSegsForFollowers, liveSegsInStore) && attempts > 0)) {
|
|
595
|
+
if (!this.allowedToSet) {
|
|
596
|
+
debug(`[${this.sessionId}]: We are about to switch away from LIVE. Abort fetching from Store`);
|
|
597
|
+
break;
|
|
598
|
+
}
|
|
599
|
+
if (leadersMediaSeqRaw <= this.lastRequestedMediaSeqRaw) {
|
|
600
|
+
isLeader = await this.sessionLiveStateStore.isLeader(this.instanceId);
|
|
601
|
+
if (isLeader) {
|
|
602
|
+
debug(`[${this.instanceId}][${this.sessionId}]: I'm the new leader`);
|
|
603
|
+
return;
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
if (this._containsSegment(this.liveSegsForFollowers, liveSegsInStore)) {
|
|
607
|
+
debug(`[${this.sessionId}]: FOLLOWER: _containsSegment=true,${leadersMediaSeqRaw},${this.lastRequestedMediaSeqRaw}`);
|
|
608
|
+
}
|
|
588
609
|
const segDur = this._getAnyFirstSegmentDurationMs() || DEFAULT_PLAYHEAD_INTERVAL_MS;
|
|
589
610
|
const waitTimeMs = parseInt(segDur / 3, 10);
|
|
590
611
|
debug(`[${this.sessionId}]: FOLLOWER: Cannot find anything NEW in store... Will check again in ${waitTimeMs}ms (Tries left=[${attempts}])`);
|
|
591
612
|
await timer(waitTimeMs);
|
|
592
613
|
this.timerCompensation = false;
|
|
593
614
|
leadersMediaSeqRaw = await this.sessionLiveState.get("lastRequestedMediaSeqRaw");
|
|
615
|
+
liveSegsInStore = await this.sessionLiveState.get("liveSegsForFollowers");
|
|
594
616
|
attempts--;
|
|
595
617
|
}
|
|
596
|
-
|
|
618
|
+
// FINALLY
|
|
597
619
|
if (leadersMediaSeqRaw <= this.lastRequestedMediaSeqRaw) {
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
debug(`[${this.instanceId}][${this.sessionId}]: I'm the new leader`);
|
|
601
|
-
return;
|
|
602
|
-
} else {
|
|
603
|
-
debug(`[${this.instanceId}][${this.sessionId}]: The leader is still alive`);
|
|
604
|
-
return;
|
|
605
|
-
}
|
|
620
|
+
debug(`[${this.instanceId}][${this.sessionId}]: The leader is still alive`);
|
|
621
|
+
return;
|
|
606
622
|
}
|
|
607
|
-
|
|
608
623
|
// Follower updates its manifest building blocks (segment holders & counts)
|
|
609
624
|
this.lastRequestedMediaSeqRaw = leadersMediaSeqRaw;
|
|
610
|
-
this.liveSegsForFollowers =
|
|
625
|
+
this.liveSegsForFollowers = liveSegsInStore;
|
|
611
626
|
debug(`[${this.sessionId}]: These are the segments from store: [${JSON.stringify(this.liveSegsForFollowers)}]`);
|
|
612
627
|
this._updateLiveSegQueue();
|
|
613
628
|
return;
|
|
@@ -807,7 +822,7 @@ class SessionLive {
|
|
|
807
822
|
const leadersCurrentMseqRaw = await this.sessionLiveState.get("lastRequestedMediaSeqRaw");
|
|
808
823
|
const counts = await this.sessionLiveState.get("firstCounts");
|
|
809
824
|
const leadersFirstMseqRaw = counts.liveSourceMseqCount;
|
|
810
|
-
if (leadersCurrentMseqRaw !== null && leadersCurrentMseqRaw
|
|
825
|
+
if (leadersCurrentMseqRaw !== null && leadersCurrentMseqRaw > currentMseqRaw) {
|
|
811
826
|
// if leader never had any segs from prev mseq
|
|
812
827
|
if (leadersFirstMseqRaw !== null && leadersFirstMseqRaw === leadersCurrentMseqRaw) {
|
|
813
828
|
// Follower updates it's manifest ingedients (segment holders & counts)
|
|
@@ -855,8 +870,8 @@ class SessionLive {
|
|
|
855
870
|
// Do not replace old data with empty data
|
|
856
871
|
if (segListSize > 0) {
|
|
857
872
|
debug(`[${this.sessionId}]: LEADER: Adding data to store!`);
|
|
858
|
-
await this.sessionLiveState.set("liveSegsForFollowers", this.liveSegsForFollowers);
|
|
859
873
|
await this.sessionLiveState.set("lastRequestedMediaSeqRaw", this.lastRequestedMediaSeqRaw);
|
|
874
|
+
await this.sessionLiveState.set("liveSegsForFollowers", this.liveSegsForFollowers);
|
|
860
875
|
}
|
|
861
876
|
}
|
|
862
877
|
|
|
@@ -1435,6 +1450,26 @@ class SessionLive {
|
|
|
1435
1450
|
}
|
|
1436
1451
|
return true;
|
|
1437
1452
|
}
|
|
1453
|
+
|
|
1454
|
+
_containsSegment(segments, newSegments) {
|
|
1455
|
+
if (!segments || !newSegments) {
|
|
1456
|
+
return false;
|
|
1457
|
+
}
|
|
1458
|
+
if (Object.keys(segments).length === 0 || Object.keys(newSegments).length === 0) {
|
|
1459
|
+
return false;
|
|
1460
|
+
}
|
|
1461
|
+
const someBw = Object.keys(segments)[0];
|
|
1462
|
+
const segList = segments[someBw];
|
|
1463
|
+
const mostRecentSegment = segList[segList.length - 1];
|
|
1464
|
+
|
|
1465
|
+
const segListNew = newSegments[someBw];
|
|
1466
|
+
const mostRecentSegmentNew = segListNew[segListNew.length - 1];
|
|
1467
|
+
|
|
1468
|
+
if (mostRecentSegmentNew.uri === mostRecentSegment.uri) {
|
|
1469
|
+
return true;
|
|
1470
|
+
}
|
|
1471
|
+
return false;
|
|
1472
|
+
}
|
|
1438
1473
|
}
|
|
1439
1474
|
|
|
1440
1475
|
module.exports = SessionLive;
|
|
@@ -307,9 +307,6 @@ class StreamSwitcher {
|
|
|
307
307
|
liveSegments = await sessionLive.getCurrentMediaSequenceSegments();
|
|
308
308
|
liveCounts = await sessionLive.getCurrentMediaAndDiscSequenceCount();
|
|
309
309
|
|
|
310
|
-
await sessionLive.resetSession();
|
|
311
|
-
sessionLive.resetLiveStoreAsync(RESET_DELAY); // In parallel
|
|
312
|
-
|
|
313
310
|
if (scheduleObj && !scheduleObj.duration) {
|
|
314
311
|
debug(`[${this.sessionId}]: Cannot switch VOD. No duration specified for schedule item: [${scheduleObj.assetId}]`);
|
|
315
312
|
}
|
|
@@ -331,6 +328,9 @@ class StreamSwitcher {
|
|
|
331
328
|
await session.setCurrentMediaAndDiscSequenceCount(liveCounts.mediaSeq, liveCounts.discSeq);
|
|
332
329
|
await session.setCurrentMediaSequenceSegments(liveSegments.currMseqSegs, liveSegments.segCount);
|
|
333
330
|
|
|
331
|
+
await sessionLive.resetSession();
|
|
332
|
+
sessionLive.resetLiveStoreAsync(RESET_DELAY); // In parallel
|
|
333
|
+
|
|
334
334
|
this.working = false;
|
|
335
335
|
this.streamTypeLive = false;
|
|
336
336
|
debug(`[${this.sessionId}]: [ Switched from LIVE->V2L ]`);
|
|
@@ -349,8 +349,6 @@ class StreamSwitcher {
|
|
|
349
349
|
this.eventId = scheduleObj.eventId;
|
|
350
350
|
liveSegments = await sessionLive.getCurrentMediaSequenceSegments();
|
|
351
351
|
liveCounts = await sessionLive.getCurrentMediaAndDiscSequenceCount();
|
|
352
|
-
await sessionLive.resetSession();
|
|
353
|
-
sessionLive.resetLiveStoreAsync(RESET_DELAY); // In parallel
|
|
354
352
|
|
|
355
353
|
eventSegments = await session.getTruncatedVodSegments(scheduleObj.uri, scheduleObj.duration / 1000);
|
|
356
354
|
if (!eventSegments) {
|
|
@@ -369,9 +367,11 @@ class StreamSwitcher {
|
|
|
369
367
|
const prerollSegments = this.prerollsCache[this.sessionId].segments;
|
|
370
368
|
eventSegments = this._mergeSegments(prerollSegments, eventSegments, true);
|
|
371
369
|
}
|
|
372
|
-
|
|
373
370
|
await session.setCurrentMediaSequenceSegments(eventSegments, 0, true);
|
|
374
371
|
|
|
372
|
+
await sessionLive.resetSession();
|
|
373
|
+
sessionLive.resetLiveStoreAsync(RESET_DELAY); // In parallel
|
|
374
|
+
|
|
375
375
|
this.working = false;
|
|
376
376
|
this.streamTypeLive = false;
|
|
377
377
|
debug(`[${this.sessionId}]: Switched from LIVE->VOD`);
|