eyevinn-channel-engine 4.2.10 → 4.3.0
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/dist/engine/server.d.ts +2 -0
- package/dist/engine/server.js +5 -0
- package/dist/engine/session.d.ts +2 -0
- package/dist/engine/session.js +156 -151
- package/dist/engine/session_state.js +33 -18
- package/dist/package.json +2 -2
- package/engine/server.ts +7 -0
- package/engine/session.js +26 -24
- package/engine/session_state.js +13 -1
- package/package.json +2 -2
package/dist/engine/server.d.ts
CHANGED
|
@@ -17,6 +17,7 @@ export interface ChannelEngineOpts {
|
|
|
17
17
|
subtitleSliceEndpoint?: string;
|
|
18
18
|
useVTTSubtitles?: boolean;
|
|
19
19
|
alwaysNewSegments?: boolean;
|
|
20
|
+
partialStoreHLSVod?: boolean;
|
|
20
21
|
alwaysMapBandwidthByNearest?: boolean;
|
|
21
22
|
diffCompensationRate?: number;
|
|
22
23
|
staticDirectory?: string;
|
|
@@ -127,6 +128,7 @@ export declare class ChannelEngine {
|
|
|
127
128
|
private subtitleSliceEndpoint;
|
|
128
129
|
private useVTTSubtitles;
|
|
129
130
|
private alwaysNewSegments;
|
|
131
|
+
private partialStoreHLSVod;
|
|
130
132
|
private alwaysMapBandwidthByNearest;
|
|
131
133
|
private defaultSlateUri?;
|
|
132
134
|
private slateDuration?;
|
package/dist/engine/server.js
CHANGED
|
@@ -89,6 +89,10 @@ var ChannelEngine = /** @class */ (function () {
|
|
|
89
89
|
if (options && options.alwaysNewSegments) {
|
|
90
90
|
this.alwaysNewSegments = true;
|
|
91
91
|
}
|
|
92
|
+
this.partialStoreHLSVod = false;
|
|
93
|
+
if (options && options.partialStoreHLSVod) {
|
|
94
|
+
this.partialStoreHLSVod = true;
|
|
95
|
+
}
|
|
92
96
|
this.alwaysMapBandwidthByNearest = false;
|
|
93
97
|
if (options && options.alwaysMapBandwidthByNearest) {
|
|
94
98
|
this.alwaysMapBandwidthByNearest = true;
|
|
@@ -441,6 +445,7 @@ var ChannelEngine = /** @class */ (function () {
|
|
|
441
445
|
subtitleSliceEndpoint: this.subtitleSliceEndpoint,
|
|
442
446
|
useVTTSubtitles: this.useVTTSubtitles,
|
|
443
447
|
alwaysNewSegments: options.alwaysNewSegments,
|
|
448
|
+
partialStoreHLSVod: options.partialStoreHLSVod,
|
|
444
449
|
alwaysMapBandwidthByNearest: options.alwaysMapBandwidthByNearest,
|
|
445
450
|
noSessionDataTags: options.noSessionDataTags,
|
|
446
451
|
playheadDiffThreshold: channel.options && channel.options.playheadDiffThreshold ? channel.options.playheadDiffThreshold : this.streamerOpts.defaultPlayheadDiffThreshold,
|
package/dist/engine/session.d.ts
CHANGED
package/dist/engine/session.js
CHANGED
|
@@ -102,10 +102,15 @@ var Session = /** @class */ (function () {
|
|
|
102
102
|
this.isAllowedToClearVodCache = null;
|
|
103
103
|
this.alwaysNewSegments = null;
|
|
104
104
|
this.alwaysMapBandwidthByNearest = null;
|
|
105
|
+
this.partialStoreHLSVod = null;
|
|
106
|
+
this.currentPlayheadRef = null;
|
|
105
107
|
if (config) {
|
|
106
108
|
if (config.alwaysNewSegments) {
|
|
107
109
|
this.alwaysNewSegments = config.alwaysNewSegments;
|
|
108
110
|
}
|
|
111
|
+
if (config.partialStoreHLSVod) {
|
|
112
|
+
this.partialStoreHLSVod = config.partialStoreHLSVod;
|
|
113
|
+
}
|
|
109
114
|
if (config.alwaysMapBandwidthByNearest) {
|
|
110
115
|
this.alwaysMapBandwidthByNearest = config.alwaysMapBandwidthByNearest;
|
|
111
116
|
}
|
|
@@ -880,7 +885,7 @@ var Session = /** @class */ (function () {
|
|
|
880
885
|
};
|
|
881
886
|
Session.prototype.getCurrentAudioManifestAsync = function (audioGroupId, audioLanguage, playbackSessionId) {
|
|
882
887
|
return __awaiter(this, void 0, void 0, function () {
|
|
883
|
-
var currentVod, sessionState, playheadState, state, DELAY_TIME_MS, ACTION,
|
|
888
|
+
var currentVod, sessionState, playheadState, state, DELAY_TIME_MS, ACTION, manifestMseq, manifestDseq, mediaSequenceValue, m3u8_2, err_5;
|
|
884
889
|
return __generator(this, function (_a) {
|
|
885
890
|
switch (_a.label) {
|
|
886
891
|
case 0:
|
|
@@ -891,7 +896,7 @@ var Session = /** @class */ (function () {
|
|
|
891
896
|
return [4 /*yield*/, this._sessionState.getValues(["discSeqAudio", "vodMediaSeqAudio"])];
|
|
892
897
|
case 1:
|
|
893
898
|
sessionState = _a.sent();
|
|
894
|
-
return [4 /*yield*/, this._playheadState.getValues(["mediaSeqAudio", "vodMediaSeqAudio"])];
|
|
899
|
+
return [4 /*yield*/, this._playheadState.getValues(["mediaSeqAudio", "vodMediaSeqAudio", "playheadRef"])];
|
|
895
900
|
case 2:
|
|
896
901
|
playheadState = _a.sent();
|
|
897
902
|
if (!(playheadState.vodMediaSeqAudio > sessionState.vodMediaSeqAudio || (playheadState.vodMediaSeqAudio < sessionState.vodMediaSeqAudio && playheadState.mediaSeqAudio === this.prevMediaSeqOffset.audio))) return [3 /*break*/, 6];
|
|
@@ -921,16 +926,12 @@ var Session = /** @class */ (function () {
|
|
|
921
926
|
currentVod = _a.sent();
|
|
922
927
|
if (!currentVod) return [3 /*break*/, 15];
|
|
923
928
|
if (!(playheadState.vodMediaSeqAudio < 2 || playheadState.mediaSeqAudio !== this.prevMediaSeqOffset.audio)) return [3 /*break*/, 11];
|
|
924
|
-
|
|
925
|
-
cacheAge = null;
|
|
926
|
-
if (this._sessionState.cache && this._sessionState.cache.currentVod.ts) {
|
|
927
|
-
cacheAge = Date.now() - this._sessionState.cache.currentVod.ts;
|
|
928
|
-
}
|
|
929
|
-
if (!(cacheAge !== null && cacheAge > AGE_THRESH)) return [3 /*break*/, 11];
|
|
929
|
+
if (!(playheadState.playheadRef > this.currentPlayheadRef)) return [3 /*break*/, 11];
|
|
930
930
|
return [4 /*yield*/, timer(500)];
|
|
931
931
|
case 8:
|
|
932
932
|
_a.sent();
|
|
933
|
-
|
|
933
|
+
this.currentPlayheadRef = playheadState.playheadRef;
|
|
934
|
+
debug("[".concat(this._sessionId, "]: While requesting audio manifest for ").concat(audioGroupId, "-").concat(audioLanguage, ", (mseq=").concat(playheadState.vodMediaSeqAudio, ")"));
|
|
934
935
|
return [4 /*yield*/, this._sessionState.clearCurrentVodCache()];
|
|
935
936
|
case 9:
|
|
936
937
|
_a.sent(); // force reading up from shared store
|
|
@@ -973,7 +974,7 @@ var Session = /** @class */ (function () {
|
|
|
973
974
|
};
|
|
974
975
|
Session.prototype.getCurrentSubtitleManifestAsync = function (subtitleGroupId, subtitleLanguage) {
|
|
975
976
|
return __awaiter(this, void 0, void 0, function () {
|
|
976
|
-
var currentVod, sessionState, playheadState, state, DELAY_TIME_MS, ACTION,
|
|
977
|
+
var currentVod, sessionState, playheadState, state, DELAY_TIME_MS, ACTION, manifestMseq, manifestDseq, mediaSequenceValue, m3u8_3, err_6;
|
|
977
978
|
return __generator(this, function (_a) {
|
|
978
979
|
switch (_a.label) {
|
|
979
980
|
case 0:
|
|
@@ -984,7 +985,7 @@ var Session = /** @class */ (function () {
|
|
|
984
985
|
return [4 /*yield*/, this._sessionState.getValues(["discSeqSubtitle", "vodMediaSeqSubtitle"])];
|
|
985
986
|
case 1:
|
|
986
987
|
sessionState = _a.sent();
|
|
987
|
-
return [4 /*yield*/, this._playheadState.getValues(["mediaSeqSubtitle", "vodMediaSeqSubtitle"])];
|
|
988
|
+
return [4 /*yield*/, this._playheadState.getValues(["mediaSeqSubtitle", "vodMediaSeqSubtitle", "playheadRef"])];
|
|
988
989
|
case 2:
|
|
989
990
|
playheadState = _a.sent();
|
|
990
991
|
if (!(playheadState.vodMediaSeqSubtitle > sessionState.vodMediaSeqSubtitle || (playheadState.vodMediaSeqSubtitle < sessionState.vodMediaSeqSubtitle && playheadState.mediaSeqSubtitle === this.prevMediaSeqOffset.subtitle))) return [3 /*break*/, 6];
|
|
@@ -1014,16 +1015,12 @@ var Session = /** @class */ (function () {
|
|
|
1014
1015
|
currentVod = _a.sent();
|
|
1015
1016
|
if (!currentVod) return [3 /*break*/, 15];
|
|
1016
1017
|
if (!(playheadState.vodMediaSeqSubtitle < 2 || playheadState.mediaSeqSubtitle !== this.prevMediaSeqOffset.subtitle)) return [3 /*break*/, 11];
|
|
1017
|
-
|
|
1018
|
-
cacheAge = null;
|
|
1019
|
-
if (this._sessionState.cache && this._sessionState.cache.currentVod.ts) {
|
|
1020
|
-
cacheAge = Date.now() - this._sessionState.cache.currentVod.ts;
|
|
1021
|
-
}
|
|
1022
|
-
if (!(cacheAge !== null && cacheAge > AGE_THRESH)) return [3 /*break*/, 11];
|
|
1018
|
+
if (!(playheadState.playheadRef > this.currentPlayheadRef)) return [3 /*break*/, 11];
|
|
1023
1019
|
return [4 /*yield*/, timer(500)];
|
|
1024
1020
|
case 8:
|
|
1025
1021
|
_a.sent();
|
|
1026
|
-
|
|
1022
|
+
this.currentPlayheadRef = playheadState.playheadRef;
|
|
1023
|
+
debug("[".concat(this._sessionId, "]: While requesting subtitle manifest for ").concat(subtitleGroupId, "-").concat(subtitleLanguage, ", (mseq=").concat(playheadState.vodMediaSeqSubtitle, ")"));
|
|
1027
1024
|
return [4 /*yield*/, this._sessionState.clearCurrentVodCache()];
|
|
1028
1025
|
case 9:
|
|
1029
1026
|
_a.sent(); // force reading up from shared store
|
|
@@ -1704,19 +1701,19 @@ var Session = /** @class */ (function () {
|
|
|
1704
1701
|
};
|
|
1705
1702
|
Session.prototype._insertSlate = function (currentVod) {
|
|
1706
1703
|
return __awaiter(this, void 0, void 0, function () {
|
|
1707
|
-
var slateVod, sessionState, endValue, endValueAudio, lastDiscontinuity, lastDiscontinuityAudio, isLeader;
|
|
1708
|
-
return __generator(this, function (
|
|
1709
|
-
switch (
|
|
1704
|
+
var slateVod, sessionState, endValue, endValueAudio, lastDiscontinuity, lastDiscontinuityAudio, isLeader, _a;
|
|
1705
|
+
return __generator(this, function (_b) {
|
|
1706
|
+
switch (_b.label) {
|
|
1710
1707
|
case 0:
|
|
1711
1708
|
if (!this.slateUri) return [3 /*break*/, 14];
|
|
1712
1709
|
console.error("[".concat(this._sessionId, "]: Will insert slate"));
|
|
1713
1710
|
return [4 /*yield*/, this._loadSlate(currentVod)];
|
|
1714
1711
|
case 1:
|
|
1715
|
-
slateVod =
|
|
1712
|
+
slateVod = _b.sent();
|
|
1716
1713
|
debug("[".concat(this._sessionId, "]: slate loaded"));
|
|
1717
1714
|
return [4 /*yield*/, this._sessionState.getValues(["slateCount", "mediaSeq", "discSeq", "mediaSeqAudio", "discSeqAudio"])];
|
|
1718
1715
|
case 2:
|
|
1719
|
-
sessionState =
|
|
1716
|
+
sessionState = _b.sent();
|
|
1720
1717
|
endValue = 0;
|
|
1721
1718
|
endValueAudio = 0;
|
|
1722
1719
|
lastDiscontinuity = 0;
|
|
@@ -1735,37 +1732,38 @@ var Session = /** @class */ (function () {
|
|
|
1735
1732
|
}
|
|
1736
1733
|
return [4 /*yield*/, this._sessionStateStore.isLeader(this._instanceId)];
|
|
1737
1734
|
case 3:
|
|
1738
|
-
isLeader =
|
|
1735
|
+
isLeader = _b.sent();
|
|
1739
1736
|
return [4 /*yield*/, this._sessionState.set("vodMediaSeqVideo", 0)];
|
|
1740
1737
|
case 4:
|
|
1741
|
-
|
|
1738
|
+
_b.sent();
|
|
1742
1739
|
return [4 /*yield*/, this._sessionState.set("vodMediaSeqAudio", 0)];
|
|
1743
1740
|
case 5:
|
|
1744
|
-
|
|
1741
|
+
_b.sent();
|
|
1745
1742
|
return [4 /*yield*/, this._sessionState.set("state", SessionState.VOD_NEXT_INITIATING)];
|
|
1746
1743
|
case 6:
|
|
1747
|
-
|
|
1744
|
+
_b.sent();
|
|
1748
1745
|
return [4 /*yield*/, this._sessionState.setCurrentVod(slateVod)];
|
|
1749
1746
|
case 7:
|
|
1750
|
-
|
|
1747
|
+
_b.sent();
|
|
1751
1748
|
return [4 /*yield*/, this._sessionState.set("mediaSeq", sessionState.mediaSeq + endValue)];
|
|
1752
1749
|
case 8:
|
|
1753
|
-
|
|
1750
|
+
_b.sent();
|
|
1754
1751
|
return [4 /*yield*/, this._sessionState.set("mediaSeqAudio", sessionState.mediaSeqAudio + endValueAudio)];
|
|
1755
1752
|
case 9:
|
|
1756
|
-
|
|
1753
|
+
_b.sent();
|
|
1757
1754
|
return [4 /*yield*/, this._sessionState.set("discSeq", sessionState.discSeq + lastDiscontinuity)];
|
|
1758
1755
|
case 10:
|
|
1759
|
-
|
|
1756
|
+
_b.sent();
|
|
1760
1757
|
return [4 /*yield*/, this._sessionState.set("discSeqAudio", sessionState.discSeqAudio + lastDiscontinuityAudio)];
|
|
1761
1758
|
case 11:
|
|
1762
|
-
|
|
1759
|
+
_b.sent();
|
|
1763
1760
|
return [4 /*yield*/, this._sessionState.set("slateCount", sessionState.slateCount + 1)];
|
|
1764
1761
|
case 12:
|
|
1765
|
-
|
|
1762
|
+
_b.sent();
|
|
1763
|
+
_a = this;
|
|
1766
1764
|
return [4 /*yield*/, this._playheadState.set("playheadRef", Date.now(), isLeader)];
|
|
1767
1765
|
case 13:
|
|
1768
|
-
_a.sent();
|
|
1766
|
+
_a.currentPlayheadRef = _b.sent();
|
|
1769
1767
|
cloudWatchLog(!this.cloudWatchLogging, 'engine-session', { event: 'slateInserted', channel: this._sessionId });
|
|
1770
1768
|
return [2 /*return*/, slateVod];
|
|
1771
1769
|
case 14: return [2 /*return*/, null];
|
|
@@ -1775,19 +1773,19 @@ var Session = /** @class */ (function () {
|
|
|
1775
1773
|
};
|
|
1776
1774
|
Session.prototype._tickAsync = function () {
|
|
1777
1775
|
return __awaiter(this, void 0, void 0, function () {
|
|
1778
|
-
var newVod, sessionState, isLeader, currentVod, vodResponse, _a, nextVodPromise, nextVodStart, _b, loadPromise, hlsOpts, _c, mediaManifestLoader, audioManifestLoader, loadStart, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, err_7,
|
|
1776
|
+
var newVod, sessionState, isLeader, currentVod, vodResponse, _a, nextVodPromise, nextVodStart, _b, loadPromise, hlsOpts, _c, mediaManifestLoader, audioManifestLoader, loadStart, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, err_7, _t, length_1, endMseqValue, endMseqValueAudio, endMseqValueSubtitle, lastDiscontinuity, lastDiscontinuityAudio, lastDiscontinuitySubtitle, _u, vodPromise, gracePeriod, nextVodStart, _v, loadPromise, hlsOpts, _w, mediaManifestLoader, audioManifestLoader, loadStart, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, diffMs, err_8, startTS, _10, mSeq, currentVod_2, dSeq, mSeqOffset, reloadBehind, segments, playheadState, nextMseq, _11, _12, err_9;
|
|
1779
1777
|
var _this = this;
|
|
1780
|
-
return __generator(this, function (
|
|
1781
|
-
switch (
|
|
1778
|
+
return __generator(this, function (_13) {
|
|
1779
|
+
switch (_13.label) {
|
|
1782
1780
|
case 0: return [4 /*yield*/, this._sessionState.getValues(["state", "assetId", "vodMediaSeqVideo", "vodMediaSeqAudio", "vodMediaSeqSubtitle", "mediaSeq", "mediaSeqAudio", "mediaSeqSubtitle", "discSeq", "discSeqAudio", "discSeqSubtitle", "nextVod"])];
|
|
1783
1781
|
case 1:
|
|
1784
|
-
sessionState =
|
|
1782
|
+
sessionState = _13.sent();
|
|
1785
1783
|
return [4 /*yield*/, this._sessionStateStore.isLeader(this._instanceId)];
|
|
1786
1784
|
case 2:
|
|
1787
|
-
isLeader =
|
|
1785
|
+
isLeader = _13.sent();
|
|
1788
1786
|
return [4 /*yield*/, this._sessionState.getCurrentVod()];
|
|
1789
1787
|
case 3:
|
|
1790
|
-
currentVod =
|
|
1788
|
+
currentVod = _13.sent();
|
|
1791
1789
|
if (!sessionState.state) {
|
|
1792
1790
|
sessionState.state = SessionState.VOD_INIT;
|
|
1793
1791
|
}
|
|
@@ -1803,15 +1801,15 @@ var Session = /** @class */ (function () {
|
|
|
1803
1801
|
}
|
|
1804
1802
|
return [3 /*break*/, 104];
|
|
1805
1803
|
case 4:
|
|
1806
|
-
|
|
1804
|
+
_13.trys.push([4, 32, , 35]);
|
|
1807
1805
|
// Needed if store was reset
|
|
1808
1806
|
return [4 /*yield*/, this._sessionStateStore.clearLeaderCache()];
|
|
1809
1807
|
case 5:
|
|
1810
1808
|
// Needed if store was reset
|
|
1811
|
-
|
|
1809
|
+
_13.sent();
|
|
1812
1810
|
return [4 /*yield*/, this._sessionStateStore.isLeader(this._instanceId)];
|
|
1813
1811
|
case 6:
|
|
1814
|
-
isLeader =
|
|
1812
|
+
isLeader = _13.sent();
|
|
1815
1813
|
nextVodPromise = void 0;
|
|
1816
1814
|
if (sessionState.state === SessionState.VOD_INIT) {
|
|
1817
1815
|
debug("[".concat(this._sessionId, "]: state=VOD_INIT"));
|
|
@@ -1825,11 +1823,11 @@ var Session = /** @class */ (function () {
|
|
|
1825
1823
|
nextVodStart = Date.now();
|
|
1826
1824
|
return [4 /*yield*/, nextVodPromise];
|
|
1827
1825
|
case 7:
|
|
1828
|
-
vodResponse =
|
|
1826
|
+
vodResponse = _13.sent();
|
|
1829
1827
|
_b = sessionState;
|
|
1830
1828
|
return [4 /*yield*/, this._sessionState.set("nextVod", vodResponse)];
|
|
1831
1829
|
case 8:
|
|
1832
|
-
_b.nextVod =
|
|
1830
|
+
_b.nextVod = _13.sent();
|
|
1833
1831
|
cloudWatchLog(!this.cloudWatchLogging, 'engine-session', { event: 'nextVod', channel: this._sessionId, reqTimeMs: Date.now() - nextVodStart });
|
|
1834
1832
|
loadPromise = void 0;
|
|
1835
1833
|
if (!!vodResponse.type) return [3 /*break*/, 12];
|
|
@@ -1840,7 +1838,8 @@ var Session = /** @class */ (function () {
|
|
|
1840
1838
|
subtitleSliceEndpoint: this.subtitleSliceEndpoint,
|
|
1841
1839
|
shouldContainSubtitles: this.use_vtt_subtitles,
|
|
1842
1840
|
expectedSubtitleTracks: this._subtitleTracks,
|
|
1843
|
-
alwaysMapBandwidthByNearest: this.alwaysMapBandwidthByNearest
|
|
1841
|
+
alwaysMapBandwidthByNearest: this.alwaysMapBandwidthByNearest,
|
|
1842
|
+
skipSerializeMediaSequences: this.partialStoreHLSVod
|
|
1844
1843
|
};
|
|
1845
1844
|
newVod = new HLSVod(vodResponse.uri, [], vodResponse.unixTs, vodResponse.offset * 1000, m3u8Header(this._instanceId), hlsOpts);
|
|
1846
1845
|
if (vodResponse.timedMetadata) {
|
|
@@ -1852,12 +1851,12 @@ var Session = /** @class */ (function () {
|
|
|
1852
1851
|
if (!vodResponse.desiredDuration) return [3 /*break*/, 10];
|
|
1853
1852
|
return [4 /*yield*/, this._truncateVod(vodResponse)];
|
|
1854
1853
|
case 9:
|
|
1855
|
-
_c =
|
|
1854
|
+
_c = _13.sent(), mediaManifestLoader = _c.mediaManifestLoader, audioManifestLoader = _c.audioManifestLoader;
|
|
1856
1855
|
loadPromise = currentVod.load(null, mediaManifestLoader, audioManifestLoader);
|
|
1857
1856
|
return [3 /*break*/, 11];
|
|
1858
1857
|
case 10:
|
|
1859
1858
|
loadPromise = currentVod.load();
|
|
1860
|
-
|
|
1859
|
+
_13.label = 11;
|
|
1861
1860
|
case 11: return [3 /*break*/, 13];
|
|
1862
1861
|
case 12:
|
|
1863
1862
|
if (vodResponse.type === 'gap') {
|
|
@@ -1869,12 +1868,12 @@ var Session = /** @class */ (function () {
|
|
|
1869
1868
|
}).catch(reject);
|
|
1870
1869
|
});
|
|
1871
1870
|
}
|
|
1872
|
-
|
|
1871
|
+
_13.label = 13;
|
|
1873
1872
|
case 13:
|
|
1874
1873
|
loadStart = Date.now();
|
|
1875
1874
|
return [4 /*yield*/, loadPromise];
|
|
1876
1875
|
case 14:
|
|
1877
|
-
|
|
1876
|
+
_13.sent();
|
|
1878
1877
|
cloudWatchLog(!this.cloudWatchLogging, 'engine-session', { event: 'loadVod', channel: this._sessionId, loadTimeMs: Date.now() - loadStart });
|
|
1879
1878
|
debug("[".concat(this._sessionId, "]: first VOD loaded"));
|
|
1880
1879
|
debug("[".concat(this._sessionId, "]: ").concat(currentVod.getDeltaTimes()));
|
|
@@ -1885,42 +1884,39 @@ var Session = /** @class */ (function () {
|
|
|
1885
1884
|
return [4 /*yield*/, this._sessionState.set("mediaSeq", 0)];
|
|
1886
1885
|
case 15:
|
|
1887
1886
|
//debug(newVod);
|
|
1888
|
-
_d.mediaSeq =
|
|
1887
|
+
_d.mediaSeq = _13.sent();
|
|
1889
1888
|
_e = sessionState;
|
|
1890
1889
|
return [4 /*yield*/, this._sessionState.set("mediaSeqAudio", 0)];
|
|
1891
1890
|
case 16:
|
|
1892
|
-
_e.mediaSeqAudio =
|
|
1891
|
+
_e.mediaSeqAudio = _13.sent();
|
|
1893
1892
|
_f = sessionState;
|
|
1894
1893
|
return [4 /*yield*/, this._sessionState.set("mediaSeqSubtitle", 0)];
|
|
1895
1894
|
case 17:
|
|
1896
|
-
_f.mediaSeqSubtitle =
|
|
1895
|
+
_f.mediaSeqSubtitle = _13.sent();
|
|
1897
1896
|
_g = sessionState;
|
|
1898
1897
|
return [4 /*yield*/, this._sessionState.set("discSeq", 0)];
|
|
1899
1898
|
case 18:
|
|
1900
|
-
_g.discSeq =
|
|
1899
|
+
_g.discSeq = _13.sent();
|
|
1901
1900
|
_h = sessionState;
|
|
1902
1901
|
return [4 /*yield*/, this._sessionState.set("discSeqAudio", 0)];
|
|
1903
1902
|
case 19:
|
|
1904
|
-
_h.discSeqAudio =
|
|
1903
|
+
_h.discSeqAudio = _13.sent();
|
|
1905
1904
|
_j = sessionState;
|
|
1906
1905
|
return [4 /*yield*/, this._sessionState.set("discSeqSubtitle", 0)];
|
|
1907
1906
|
case 20:
|
|
1908
|
-
_j.discSeqSubtitle =
|
|
1907
|
+
_j.discSeqSubtitle = _13.sent();
|
|
1909
1908
|
_k = sessionState;
|
|
1910
1909
|
return [4 /*yield*/, this._sessionState.set("vodMediaSeqVideo", 0)];
|
|
1911
1910
|
case 21:
|
|
1912
|
-
_k.vodMediaSeqVideo =
|
|
1911
|
+
_k.vodMediaSeqVideo = _13.sent();
|
|
1913
1912
|
_l = sessionState;
|
|
1914
1913
|
return [4 /*yield*/, this._sessionState.set("vodMediaSeqAudio", 0)];
|
|
1915
1914
|
case 22:
|
|
1916
|
-
_l.vodMediaSeqAudio =
|
|
1915
|
+
_l.vodMediaSeqAudio = _13.sent();
|
|
1917
1916
|
_m = sessionState;
|
|
1918
1917
|
return [4 /*yield*/, this._sessionState.set("vodMediaSeqSubtitle", 0)];
|
|
1919
1918
|
case 23:
|
|
1920
|
-
_m.vodMediaSeqSubtitle =
|
|
1921
|
-
return [4 /*yield*/, this._playheadState.set("playheadRef", Date.now(), isLeader)];
|
|
1922
|
-
case 24:
|
|
1923
|
-
_10.sent();
|
|
1919
|
+
_m.vodMediaSeqSubtitle = _13.sent();
|
|
1924
1920
|
this.produceEvent({
|
|
1925
1921
|
type: 'NOW_PLAYING',
|
|
1926
1922
|
data: {
|
|
@@ -1930,30 +1926,34 @@ var Session = /** @class */ (function () {
|
|
|
1930
1926
|
});
|
|
1931
1927
|
_o = sessionState;
|
|
1932
1928
|
return [4 /*yield*/, this._sessionState.set("state", SessionState.VOD_PLAYING)];
|
|
1933
|
-
case
|
|
1934
|
-
_o.state =
|
|
1929
|
+
case 24:
|
|
1930
|
+
_o.state = _13.sent();
|
|
1935
1931
|
_p = sessionState;
|
|
1936
1932
|
return [4 /*yield*/, this._sessionState.setCurrentVod(currentVod, { ttl: currentVod.getDuration() * 1000 })];
|
|
1933
|
+
case 25:
|
|
1934
|
+
_p.currentVod = _13.sent();
|
|
1935
|
+
_q = this;
|
|
1936
|
+
return [4 /*yield*/, this._playheadState.set("playheadRef", Date.now(), isLeader)];
|
|
1937
1937
|
case 26:
|
|
1938
|
-
|
|
1938
|
+
_q.currentPlayheadRef = _13.sent();
|
|
1939
1939
|
return [4 /*yield*/, this._sessionState.remove("nextVod")];
|
|
1940
1940
|
case 27:
|
|
1941
|
-
|
|
1941
|
+
_13.sent();
|
|
1942
1942
|
return [2 /*return*/];
|
|
1943
1943
|
case 28:
|
|
1944
1944
|
debug("[".concat(this._sessionId, "]: not a leader so will go directly to state VOD_PLAYING"));
|
|
1945
|
-
|
|
1945
|
+
_r = sessionState;
|
|
1946
1946
|
return [4 /*yield*/, this._sessionState.set("state", SessionState.VOD_PLAYING)];
|
|
1947
1947
|
case 29:
|
|
1948
|
-
|
|
1949
|
-
|
|
1948
|
+
_r.state = _13.sent();
|
|
1949
|
+
_s = sessionState;
|
|
1950
1950
|
return [4 /*yield*/, this._sessionState.getCurrentVod()];
|
|
1951
1951
|
case 30:
|
|
1952
|
-
|
|
1952
|
+
_s.currentVod = _13.sent();
|
|
1953
1953
|
return [2 /*return*/];
|
|
1954
1954
|
case 31: return [3 /*break*/, 35];
|
|
1955
1955
|
case 32:
|
|
1956
|
-
err_7 =
|
|
1956
|
+
err_7 = _13.sent();
|
|
1957
1957
|
console.error("[".concat(this._sessionId, "]: Failed to init first VOD"));
|
|
1958
1958
|
if (this._assetManager.handleError) {
|
|
1959
1959
|
this._assetManager.handleError(new Error("Failed to init first VOD"), vodResponse);
|
|
@@ -1962,10 +1962,10 @@ var Session = /** @class */ (function () {
|
|
|
1962
1962
|
debug(err_7);
|
|
1963
1963
|
return [4 /*yield*/, this._sessionState.remove("nextVod")];
|
|
1964
1964
|
case 33:
|
|
1965
|
-
|
|
1965
|
+
_13.sent();
|
|
1966
1966
|
return [4 /*yield*/, this._insertSlate(currentVod)];
|
|
1967
1967
|
case 34:
|
|
1968
|
-
currentVod =
|
|
1968
|
+
currentVod = _13.sent();
|
|
1969
1969
|
if (!currentVod) {
|
|
1970
1970
|
debug("No slate to load");
|
|
1971
1971
|
throw err_7;
|
|
@@ -2000,14 +2000,14 @@ var Session = /** @class */ (function () {
|
|
|
2000
2000
|
debug("[".concat(this._sessionId, "]: state=VOD_PLAYING, current[").concat(sessionState.vodMediaSeqVideo, "], prev[").concat(this.prevVodMediaSeq.video, "], total[").concat(currentVod.getLiveMediaSequencesCount(), "]"));
|
|
2001
2001
|
return [4 /*yield*/, this._sessionState.clearCurrentVodCache()];
|
|
2002
2002
|
case 36:
|
|
2003
|
-
|
|
2003
|
+
_13.sent();
|
|
2004
2004
|
return [4 /*yield*/, this._sessionState.getCurrentVod()];
|
|
2005
2005
|
case 37:
|
|
2006
|
-
currentVod =
|
|
2006
|
+
currentVod = _13.sent();
|
|
2007
2007
|
this.prevVodMediaSeq.video = sessionState.vodMediaSeqVideo;
|
|
2008
2008
|
this.prevVodMediaSeq.audio = sessionState.vodMediaSeqAudio;
|
|
2009
2009
|
this.prevVodMediaSeq.subtitle = sessionState.vodMediaSeqSubtitle;
|
|
2010
|
-
|
|
2010
|
+
_13.label = 38;
|
|
2011
2011
|
case 38: return [3 /*break*/, 40];
|
|
2012
2012
|
case 39:
|
|
2013
2013
|
// Handle edge case where Leader loaded next vod but Follower remained in state=VOD_PLAYING
|
|
@@ -2017,7 +2017,7 @@ var Session = /** @class */ (function () {
|
|
|
2017
2017
|
// Allow Follower to clear VodCache...
|
|
2018
2018
|
this.isAllowedToClearVodCache = true;
|
|
2019
2019
|
}
|
|
2020
|
-
|
|
2020
|
+
_13.label = 40;
|
|
2021
2021
|
case 40:
|
|
2022
2022
|
debug("[".concat(this._sessionId, "]: state=VOD_PLAYING (").concat(sessionState.vodMediaSeqVideo, "_").concat(sessionState.vodMediaSeqAudio, "_").concat(sessionState.vodMediaSeqSubtitle, ", ").concat(currentVod.getLiveMediaSequencesCount(), "_").concat(currentVod.getLiveMediaSequencesCount("audio"), "_").concat(currentVod.getLiveMediaSequencesCount("subtitle"), ")"));
|
|
2023
2023
|
return [2 /*return*/];
|
|
@@ -2030,15 +2030,15 @@ var Session = /** @class */ (function () {
|
|
|
2030
2030
|
this.isAllowedToClearVodCache = true;
|
|
2031
2031
|
return [2 /*return*/];
|
|
2032
2032
|
case 42:
|
|
2033
|
-
|
|
2033
|
+
_13.trys.push([42, 74, , 77]);
|
|
2034
2034
|
debug("[".concat(this._sessionId, "]: state=VOD_NEXT_INIT"));
|
|
2035
2035
|
if (!isLeader) return [3 /*break*/, 69];
|
|
2036
2036
|
if (!!currentVod) return [3 /*break*/, 44];
|
|
2037
2037
|
debug("[".concat(this._sessionId, "]: no VOD to append to, assume first VOD to init"));
|
|
2038
|
-
|
|
2038
|
+
_t = sessionState;
|
|
2039
2039
|
return [4 /*yield*/, this._sessionState.set("state", SessionState.VOD_INIT)];
|
|
2040
2040
|
case 43:
|
|
2041
|
-
|
|
2041
|
+
_t.state = _13.sent();
|
|
2042
2042
|
return [2 /*return*/];
|
|
2043
2043
|
case 44:
|
|
2044
2044
|
length_1 = currentVod.getLiveMediaSequencesCount();
|
|
@@ -2058,27 +2058,27 @@ var Session = /** @class */ (function () {
|
|
|
2058
2058
|
lastDiscontinuity = currentVod.getLastDiscontinuity();
|
|
2059
2059
|
lastDiscontinuityAudio = currentVod.getLastDiscontinuityAudio();
|
|
2060
2060
|
lastDiscontinuitySubtitle = currentVod.getLastDiscontinuitySubtitle();
|
|
2061
|
-
|
|
2061
|
+
_u = sessionState;
|
|
2062
2062
|
return [4 /*yield*/, this._sessionState.set("state", SessionState.VOD_NEXT_INITIATING)];
|
|
2063
2063
|
case 45:
|
|
2064
|
-
|
|
2064
|
+
_u.state = _13.sent();
|
|
2065
2065
|
vodPromise = this._getNextVod();
|
|
2066
2066
|
if (!(length_1 === 1)) return [3 /*break*/, 47];
|
|
2067
2067
|
gracePeriod = (this.averageSegmentDuration / 2);
|
|
2068
2068
|
debug("[".concat(this._sessionId, "]: adding a grace period before calling nextVod: ").concat(gracePeriod, "ms"));
|
|
2069
2069
|
return [4 /*yield*/, timer(gracePeriod)];
|
|
2070
2070
|
case 46:
|
|
2071
|
-
|
|
2072
|
-
|
|
2071
|
+
_13.sent();
|
|
2072
|
+
_13.label = 47;
|
|
2073
2073
|
case 47:
|
|
2074
2074
|
nextVodStart = Date.now();
|
|
2075
2075
|
return [4 /*yield*/, vodPromise];
|
|
2076
2076
|
case 48:
|
|
2077
|
-
vodResponse =
|
|
2078
|
-
|
|
2077
|
+
vodResponse = _13.sent();
|
|
2078
|
+
_v = sessionState;
|
|
2079
2079
|
return [4 /*yield*/, this._sessionState.set("nextVod", vodResponse)];
|
|
2080
2080
|
case 49:
|
|
2081
|
-
|
|
2081
|
+
_v.nextVod = _13.sent();
|
|
2082
2082
|
cloudWatchLog(!this.cloudWatchLogging, 'engine-session', { event: 'nextVod', channel: this._sessionId, reqTimeMs: Date.now() - nextVodStart });
|
|
2083
2083
|
loadPromise = void 0;
|
|
2084
2084
|
if (!!vodResponse.type) return [3 /*break*/, 53];
|
|
@@ -2089,7 +2089,8 @@ var Session = /** @class */ (function () {
|
|
|
2089
2089
|
subtitleSliceEndpoint: this.subtitleSliceEndpoint,
|
|
2090
2090
|
shouldContainSubtitles: this.use_vtt_subtitles,
|
|
2091
2091
|
expectedSubtitleTracks: this._subtitleTracks,
|
|
2092
|
-
alwaysMapBandwidthByNearest: this.alwaysMapBandwidthByNearest
|
|
2092
|
+
alwaysMapBandwidthByNearest: this.alwaysMapBandwidthByNearest,
|
|
2093
|
+
skipSerializeMediaSequences: this.partialStoreHLSVod
|
|
2093
2094
|
};
|
|
2094
2095
|
newVod = new HLSVod(vodResponse.uri, null, vodResponse.unixTs, vodResponse.offset * 1000, m3u8Header(this._instanceId), hlsOpts);
|
|
2095
2096
|
if (vodResponse.timedMetadata) {
|
|
@@ -2108,12 +2109,12 @@ var Session = /** @class */ (function () {
|
|
|
2108
2109
|
if (!vodResponse.desiredDuration) return [3 /*break*/, 51];
|
|
2109
2110
|
return [4 /*yield*/, this._truncateVod(vodResponse)];
|
|
2110
2111
|
case 50:
|
|
2111
|
-
|
|
2112
|
+
_w = _13.sent(), mediaManifestLoader = _w.mediaManifestLoader, audioManifestLoader = _w.audioManifestLoader;
|
|
2112
2113
|
loadPromise = newVod.loadAfter(currentVod, null, mediaManifestLoader, audioManifestLoader);
|
|
2113
2114
|
return [3 /*break*/, 52];
|
|
2114
2115
|
case 51:
|
|
2115
2116
|
loadPromise = newVod.loadAfter(currentVod);
|
|
2116
|
-
|
|
2117
|
+
_13.label = 52;
|
|
2117
2118
|
case 52:
|
|
2118
2119
|
if (vodResponse.diffMs) {
|
|
2119
2120
|
this.diffCompensation = vodResponse.diffMs;
|
|
@@ -2134,12 +2135,12 @@ var Session = /** @class */ (function () {
|
|
|
2134
2135
|
resolve(newVod);
|
|
2135
2136
|
}).catch(reject);
|
|
2136
2137
|
});
|
|
2137
|
-
|
|
2138
|
+
_13.label = 54;
|
|
2138
2139
|
case 54:
|
|
2139
2140
|
loadStart = Date.now();
|
|
2140
2141
|
return [4 /*yield*/, ChaosMonkey.loadVod(loadPromise)];
|
|
2141
2142
|
case 55:
|
|
2142
|
-
|
|
2143
|
+
_13.sent();
|
|
2143
2144
|
cloudWatchLog(!this.cloudWatchLogging, 'engine-session', { event: 'loadVod', channel: this._sessionId, loadTimeMs: Date.now() - loadStart });
|
|
2144
2145
|
this.leaderIsSettingNextVod = true;
|
|
2145
2146
|
debug("[".concat(this._sessionId, "]: next VOD loaded (").concat(newVod.getDeltaTimes(), ")"));
|
|
@@ -2147,57 +2148,58 @@ var Session = /** @class */ (function () {
|
|
|
2147
2148
|
debug("[".concat(this._sessionId, "]: playhead positions [A]=").concat(newVod.getPlayheadPositions("audio")));
|
|
2148
2149
|
currentVod = newVod;
|
|
2149
2150
|
debug("[".concat(this._sessionId, "]: msequences=").concat(currentVod.getLiveMediaSequencesCount(), "; audio msequences=").concat(currentVod.getLiveMediaSequencesCount("audio"), "; subtitle msequences=").concat(currentVod.getLiveMediaSequencesCount("subtitle")));
|
|
2150
|
-
|
|
2151
|
+
_x = sessionState;
|
|
2151
2152
|
return [4 /*yield*/, this._sessionState.setCurrentVod(currentVod, { ttl: currentVod.getDuration() * 1000 })];
|
|
2152
2153
|
case 56:
|
|
2153
|
-
|
|
2154
|
+
_x.currentVod = _13.sent();
|
|
2155
|
+
_y = this;
|
|
2154
2156
|
return [4 /*yield*/, this._playheadState.set("playheadRef", Date.now(), isLeader)];
|
|
2155
2157
|
case 57:
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
+
_y.currentPlayheadRef = _13.sent();
|
|
2159
|
+
_z = sessionState;
|
|
2158
2160
|
return [4 /*yield*/, this._sessionState.set("vodMediaSeqVideo", 0)];
|
|
2159
2161
|
case 58:
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
+
_z.vodMediaSeqVideo = _13.sent();
|
|
2163
|
+
_0 = sessionState;
|
|
2162
2164
|
return [4 /*yield*/, this._sessionState.set("vodMediaSeqAudio", 0)];
|
|
2163
2165
|
case 59:
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
+
_0.vodMediaSeqAudio = _13.sent();
|
|
2167
|
+
_1 = sessionState;
|
|
2166
2168
|
return [4 /*yield*/, this._sessionState.set("vodMediaSeqSubtitle", 0)];
|
|
2167
2169
|
case 60:
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
+
_1.vodMediaSeqSubtitle = _13.sent();
|
|
2171
|
+
_2 = sessionState;
|
|
2170
2172
|
return [4 /*yield*/, this._sessionState.set("mediaSeq", sessionState.mediaSeq + endMseqValue)];
|
|
2171
2173
|
case 61:
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
+
_2.mediaSeq = _13.sent();
|
|
2175
|
+
_3 = sessionState;
|
|
2174
2176
|
return [4 /*yield*/, this._sessionState.set("mediaSeqAudio", sessionState.mediaSeqAudio + endMseqValueAudio)];
|
|
2175
2177
|
case 62:
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
+
_3.mediaSeqAudio = _13.sent();
|
|
2179
|
+
_4 = sessionState;
|
|
2178
2180
|
return [4 /*yield*/, this._sessionState.set("mediaSeqSubtitle", sessionState.mediaSeqSubtitle + endMseqValueSubtitle)];
|
|
2179
2181
|
case 63:
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
+
_4.mediaSeqSubtitle = _13.sent();
|
|
2183
|
+
_5 = sessionState;
|
|
2182
2184
|
return [4 /*yield*/, this._sessionState.set("discSeq", sessionState.discSeq + lastDiscontinuity)];
|
|
2183
2185
|
case 64:
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
+
_5.discSeq = _13.sent();
|
|
2187
|
+
_6 = sessionState;
|
|
2186
2188
|
return [4 /*yield*/, this._sessionState.set("discSeqAudio", sessionState.discSeqAudio + lastDiscontinuityAudio)];
|
|
2187
2189
|
case 65:
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
+
_6.discSeqAudio = _13.sent();
|
|
2191
|
+
_7 = sessionState;
|
|
2190
2192
|
return [4 /*yield*/, this._sessionState.set("discSeqSubtitle", sessionState.discSeqSubtitle + lastDiscontinuitySubtitle)];
|
|
2191
2193
|
case 66:
|
|
2192
|
-
|
|
2194
|
+
_7.discSeqSubtitle = _13.sent();
|
|
2193
2195
|
debug("[".concat(this._sessionId, "]: new sequence data set in store V[").concat(sessionState.mediaSeq, "][").concat(sessionState.discSeq, "]_A[").concat(sessionState.mediaSeqAudio, "][").concat(sessionState.discSeqAudio, "]_S[").concat(sessionState.mediaSeqSubtitle, "][").concat(sessionState.discSeqSubtitle, "]"));
|
|
2194
2196
|
return [4 /*yield*/, this._sessionState.remove("nextVod")];
|
|
2195
2197
|
case 67:
|
|
2196
|
-
|
|
2198
|
+
_13.sent();
|
|
2197
2199
|
this.leaderIsSettingNextVod = false;
|
|
2198
2200
|
return [4 /*yield*/, this._playheadState.set("diffCompensation", this.diffCompensation, isLeader)];
|
|
2199
2201
|
case 68:
|
|
2200
|
-
|
|
2202
|
+
_13.sent();
|
|
2201
2203
|
debug("[".concat(this._sessionId, "]: sharing durrent vods diffCompensation=").concat(this.diffCompensation));
|
|
2202
2204
|
this.produceEvent({
|
|
2203
2205
|
type: 'NOW_PLAYING',
|
|
@@ -2210,19 +2212,19 @@ var Session = /** @class */ (function () {
|
|
|
2210
2212
|
case 69:
|
|
2211
2213
|
debug("[".concat(this._sessionId, "]: not a leader so will go directly to state VOD_NEXT_INITIATING"));
|
|
2212
2214
|
this.waitingForNextVod = true;
|
|
2213
|
-
|
|
2215
|
+
_8 = sessionState;
|
|
2214
2216
|
return [4 /*yield*/, this._sessionState.set("state", SessionState.VOD_NEXT_INITIATING)];
|
|
2215
2217
|
case 70:
|
|
2216
|
-
|
|
2218
|
+
_8.state = _13.sent();
|
|
2217
2219
|
// Allow Leader|Follower to clear vodCache...
|
|
2218
2220
|
this.isAllowedToClearVodCache = true;
|
|
2219
|
-
|
|
2221
|
+
_9 = sessionState;
|
|
2220
2222
|
return [4 /*yield*/, this._sessionState.getCurrentVod()];
|
|
2221
2223
|
case 71:
|
|
2222
|
-
|
|
2224
|
+
_9.currentVod = _13.sent();
|
|
2223
2225
|
return [4 /*yield*/, this._playheadState.get("diffCompensation")];
|
|
2224
2226
|
case 72:
|
|
2225
|
-
diffMs =
|
|
2227
|
+
diffMs = _13.sent();
|
|
2226
2228
|
if (diffMs) {
|
|
2227
2229
|
this.diffCompensation = diffMs;
|
|
2228
2230
|
debug("[".concat(this._sessionId, "]: Setting diffCompensation=").concat(this.diffCompensation));
|
|
@@ -2234,10 +2236,10 @@ var Session = /** @class */ (function () {
|
|
|
2234
2236
|
this.timePositionOffset = 0;
|
|
2235
2237
|
}
|
|
2236
2238
|
}
|
|
2237
|
-
|
|
2239
|
+
_13.label = 73;
|
|
2238
2240
|
case 73: return [3 /*break*/, 77];
|
|
2239
2241
|
case 74:
|
|
2240
|
-
err_8 =
|
|
2242
|
+
err_8 = _13.sent();
|
|
2241
2243
|
console.error("[".concat(this._sessionId, "]: Failed to init next VOD"));
|
|
2242
2244
|
debug("[".concat(this._sessionId, "]: ").concat(err_8));
|
|
2243
2245
|
if (this._assetManager.handleError) {
|
|
@@ -2246,10 +2248,10 @@ var Session = /** @class */ (function () {
|
|
|
2246
2248
|
cloudWatchLog(!this.cloudWatchLogging, 'engine-session', { event: 'error', on: 'nextvod', channel: this._sessionId, err: err_8, vod: vodResponse });
|
|
2247
2249
|
return [4 /*yield*/, this._sessionState.remove("nextVod")];
|
|
2248
2250
|
case 75:
|
|
2249
|
-
|
|
2251
|
+
_13.sent();
|
|
2250
2252
|
return [4 /*yield*/, this._insertSlate(currentVod)];
|
|
2251
2253
|
case 76:
|
|
2252
|
-
currentVod =
|
|
2254
|
+
currentVod = _13.sent();
|
|
2253
2255
|
if (!currentVod) {
|
|
2254
2256
|
debug("No slate to load");
|
|
2255
2257
|
throw err_8;
|
|
@@ -2259,20 +2261,20 @@ var Session = /** @class */ (function () {
|
|
|
2259
2261
|
return [3 /*break*/, 77];
|
|
2260
2262
|
case 77: return [3 /*break*/, 105];
|
|
2261
2263
|
case 78:
|
|
2262
|
-
|
|
2264
|
+
_13.trys.push([78, 98, , 99]);
|
|
2263
2265
|
debug("[".concat(this._sessionId, "]: state=VOD_RELOAD_INIT"));
|
|
2264
2266
|
if (!isLeader) return [3 /*break*/, 95];
|
|
2265
2267
|
startTS = Date.now();
|
|
2266
2268
|
// 1) To tell Follower that, Leader is working on it!
|
|
2267
|
-
|
|
2269
|
+
_10 = sessionState;
|
|
2268
2270
|
return [4 /*yield*/, this._sessionState.set("state", SessionState.VOD_RELOAD_INITIATING)];
|
|
2269
2271
|
case 79:
|
|
2270
2272
|
// 1) To tell Follower that, Leader is working on it!
|
|
2271
|
-
|
|
2273
|
+
_10.state = _13.sent();
|
|
2272
2274
|
mSeq = this.switchDataForSession.mediaSeq;
|
|
2273
2275
|
return [4 /*yield*/, this._sessionState.getCurrentVod()];
|
|
2274
2276
|
case 80:
|
|
2275
|
-
currentVod_2 =
|
|
2277
|
+
currentVod_2 = _13.sent();
|
|
2276
2278
|
if (currentVod_2.sequenceAlwaysContainNewSegments) {
|
|
2277
2279
|
// (!) will need to compensate if using this setting on HLSVod Object.
|
|
2278
2280
|
Object.keys(this.switchDataForSession.transitionSegments).forEach(function (bw) {
|
|
@@ -2292,20 +2294,20 @@ var Session = /** @class */ (function () {
|
|
|
2292
2294
|
}
|
|
2293
2295
|
return [4 /*yield*/, this._sessionState.set("mediaSeq", mSeq)];
|
|
2294
2296
|
case 81:
|
|
2295
|
-
|
|
2297
|
+
_13.sent();
|
|
2296
2298
|
return [4 /*yield*/, this._playheadState.set("mediaSeq", mSeq, isLeader)];
|
|
2297
2299
|
case 82:
|
|
2298
|
-
|
|
2300
|
+
_13.sent();
|
|
2299
2301
|
return [4 /*yield*/, this._sessionState.set("discSeq", dSeq)];
|
|
2300
2302
|
case 83:
|
|
2301
|
-
|
|
2303
|
+
_13.sent();
|
|
2302
2304
|
// TODO: support demux^
|
|
2303
2305
|
debug("[".concat(this._sessionId, "]: Setting current media and discontinuity count -> [").concat(mSeq, "]:[").concat(dSeq, "]"));
|
|
2304
2306
|
// 3) Set new media segments/currentVod, to carry on the continuity from session-live
|
|
2305
2307
|
debug("[".concat(this._sessionId, "]: LEADER: making changes to current VOD. I will also update currentVod in store."));
|
|
2306
2308
|
return [4 /*yield*/, this._playheadState.getValues(["vodMediaSeqVideo"])];
|
|
2307
2309
|
case 84:
|
|
2308
|
-
playheadState =
|
|
2310
|
+
playheadState = _13.sent();
|
|
2309
2311
|
nextMseq = playheadState.vodMediaSeqVideo + 1;
|
|
2310
2312
|
if (nextMseq > currentVod_2.getLiveMediaSequencesCount() - 1) {
|
|
2311
2313
|
nextMseq = currentVod_2.getLiveMediaSequencesCount() - 1;
|
|
@@ -2318,34 +2320,35 @@ var Session = /** @class */ (function () {
|
|
|
2318
2320
|
// ---------------------------------------------------.
|
|
2319
2321
|
// TODO: Support reloading with audioSegments and SubtitleSegments as well |
|
|
2320
2322
|
// ---------------------------------------------------'
|
|
2321
|
-
|
|
2323
|
+
_13.sent();
|
|
2322
2324
|
return [4 /*yield*/, this._sessionState.setCurrentVod(currentVod_2, { ttl: currentVod_2.getDuration() * 1000 })];
|
|
2323
2325
|
case 86:
|
|
2324
|
-
|
|
2326
|
+
_13.sent();
|
|
2325
2327
|
return [4 /*yield*/, this._sessionState.set("vodReloaded", 1)];
|
|
2326
2328
|
case 87:
|
|
2327
|
-
|
|
2329
|
+
_13.sent();
|
|
2328
2330
|
return [4 /*yield*/, this._sessionState.set("vodMediaSeqVideo", 0)];
|
|
2329
2331
|
case 88:
|
|
2330
|
-
|
|
2332
|
+
_13.sent();
|
|
2331
2333
|
return [4 /*yield*/, this._sessionState.set("vodMediaSeqAudio", 0)];
|
|
2332
2334
|
case 89:
|
|
2333
|
-
|
|
2335
|
+
_13.sent();
|
|
2334
2336
|
return [4 /*yield*/, this._sessionState.set("vodMediaSeqSubtitle", 0)];
|
|
2335
2337
|
case 90:
|
|
2336
|
-
|
|
2338
|
+
_13.sent();
|
|
2337
2339
|
return [4 /*yield*/, this._playheadState.set("vodMediaSeqVideo", 0, isLeader)];
|
|
2338
2340
|
case 91:
|
|
2339
|
-
|
|
2341
|
+
_13.sent();
|
|
2340
2342
|
return [4 /*yield*/, this._playheadState.set("vodMediaSeqAudio", 0, isLeader)];
|
|
2341
2343
|
case 92:
|
|
2342
|
-
|
|
2344
|
+
_13.sent();
|
|
2343
2345
|
return [4 /*yield*/, this._playheadState.set("vodMediaSeqSubtitle", 0, isLeader)];
|
|
2344
2346
|
case 93:
|
|
2345
|
-
|
|
2347
|
+
_13.sent();
|
|
2348
|
+
_11 = this;
|
|
2346
2349
|
return [4 /*yield*/, this._playheadState.set("playheadRef", Date.now(), isLeader)];
|
|
2347
2350
|
case 94:
|
|
2348
|
-
|
|
2351
|
+
_11.currentPlayheadRef = _13.sent();
|
|
2349
2352
|
// 4) Log to debug and cloudwatch
|
|
2350
2353
|
debug("[".concat(this._sessionId, "]: LEADER: Set new Reloaded VOD and vodMediaSeq counts in store."));
|
|
2351
2354
|
debug("[".concat(this._sessionId, "]: next VOD Reloaded (").concat(currentVod_2.getDeltaTimes(), ")"));
|
|
@@ -2355,14 +2358,14 @@ var Session = /** @class */ (function () {
|
|
|
2355
2358
|
return [2 /*return*/];
|
|
2356
2359
|
case 95:
|
|
2357
2360
|
debug("[".concat(this._sessionId, "]: not a leader so will go directly to state VOD_RELOAD_INITIATING"));
|
|
2358
|
-
|
|
2361
|
+
_12 = sessionState;
|
|
2359
2362
|
return [4 /*yield*/, this._sessionState.set("state", SessionState.VOD_RELOAD_INITIATING)];
|
|
2360
2363
|
case 96:
|
|
2361
|
-
|
|
2362
|
-
|
|
2364
|
+
_12.state = _13.sent();
|
|
2365
|
+
_13.label = 97;
|
|
2363
2366
|
case 97: return [3 /*break*/, 99];
|
|
2364
2367
|
case 98:
|
|
2365
|
-
err_9 =
|
|
2368
|
+
err_9 = _13.sent();
|
|
2366
2369
|
debug("Failed to init reload vod");
|
|
2367
2370
|
throw err_9;
|
|
2368
2371
|
case 99: return [3 /*break*/, 105];
|
|
@@ -2374,11 +2377,11 @@ var Session = /** @class */ (function () {
|
|
|
2374
2377
|
debug("[".concat(this._sessionId, "]: First mediasequence in VOD and I am not the leader so invalidate current VOD cache and fetch the new one from the leader"));
|
|
2375
2378
|
return [4 /*yield*/, this._sessionState.clearCurrentVodCache()];
|
|
2376
2379
|
case 101:
|
|
2377
|
-
|
|
2378
|
-
|
|
2380
|
+
_13.sent();
|
|
2381
|
+
_13.label = 102;
|
|
2379
2382
|
case 102:
|
|
2380
2383
|
this.waitingForNextVod = true;
|
|
2381
|
-
|
|
2384
|
+
_13.label = 103;
|
|
2382
2385
|
case 103:
|
|
2383
2386
|
// Allow Leader|Follower to clear vodCache...
|
|
2384
2387
|
this.isAllowedToClearVodCache = true;
|
|
@@ -2435,7 +2438,8 @@ var Session = /** @class */ (function () {
|
|
|
2435
2438
|
subtitleSliceEndpoint: _this.subtitleSliceEndpoint,
|
|
2436
2439
|
shouldContainSubtitles: _this.use_vtt_subtitles,
|
|
2437
2440
|
expectedSubtitleTracks: _this._subtitleTracks,
|
|
2438
|
-
alwaysMapBandwidthByNearest: _this.alwaysMapBandwidthByNearest
|
|
2441
|
+
alwaysMapBandwidthByNearest: _this.alwaysMapBandwidthByNearest,
|
|
2442
|
+
skipSerializeMediaSequences: _this.partialStoreHLSVod
|
|
2439
2443
|
};
|
|
2440
2444
|
var timestamp = Date.now();
|
|
2441
2445
|
hlsVod_1 = new HLSVod(_this.slateUri, null, timestamp, null, m3u8Header(_this._instanceId), hlsOpts);
|
|
@@ -2543,7 +2547,8 @@ var Session = /** @class */ (function () {
|
|
|
2543
2547
|
subtitleSliceEndpoint: _this.subtitleSliceEndpoint,
|
|
2544
2548
|
shouldContainSubtitles: _this.use_vtt_subtitles,
|
|
2545
2549
|
expectedSubtitleTracks: _this._subtitleTracks,
|
|
2546
|
-
alwaysMapBandwidthByNearest: _this.alwaysMapBandwidthByNearest
|
|
2550
|
+
alwaysMapBandwidthByNearest: _this.alwaysMapBandwidthByNearest,
|
|
2551
|
+
skipSerializeMediaSequences: _this.partialStoreHLSVod
|
|
2547
2552
|
};
|
|
2548
2553
|
var timestamp = Date.now();
|
|
2549
2554
|
hlsVod_2 = new HLSVod(nexVodUri, null, timestamp, null, m3u8Header(_this._instanceId), hlsOpts);
|
|
@@ -92,7 +92,7 @@ var SharedSessionState = /** @class */ (function () {
|
|
|
92
92
|
};
|
|
93
93
|
SharedSessionState.prototype.getCurrentVod = function () {
|
|
94
94
|
return __awaiter(this, void 0, void 0, function () {
|
|
95
|
-
var currentVod, hlsVod;
|
|
95
|
+
var currentVod, hlsVod, strToMB;
|
|
96
96
|
return __generator(this, function (_a) {
|
|
97
97
|
switch (_a.label) {
|
|
98
98
|
case 0:
|
|
@@ -107,16 +107,27 @@ var SharedSessionState = /** @class */ (function () {
|
|
|
107
107
|
case 1:
|
|
108
108
|
currentVod = _a.sent();
|
|
109
109
|
hlsVod = null;
|
|
110
|
-
if (currentVod)
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
110
|
+
if (!currentVod) return [3 /*break*/, 5];
|
|
111
|
+
if (!this.store.isShared()) return [3 /*break*/, 4];
|
|
112
|
+
strToMB = function (str) {
|
|
113
|
+
var bytesPerCharacter = 2; // Assuming each character takes around 2 bytes in memory
|
|
114
|
+
var stringSizeBytes = str.length * bytesPerCharacter;
|
|
115
|
+
var sizeInMegabytes = stringSizeBytes / (1024 * 1024);
|
|
116
|
+
return sizeInMegabytes.toFixed(1);
|
|
117
|
+
};
|
|
118
|
+
debug("[".concat(this.sessionId, "]: reading ").concat(currentVod.length, " characters or (").concat(strToMB(currentVod), " MB) from shared store (").concat(Date.now(), " < ").concat(this.cache.currentVod.ts + this.cache.currentVod.ttl, ")"));
|
|
119
|
+
hlsVod = new HLSVod();
|
|
120
|
+
hlsVod.fromJSON(currentVod);
|
|
121
|
+
if (!hlsVod.skipSerializeMediaSequences) return [3 /*break*/, 3];
|
|
122
|
+
return [4 /*yield*/, hlsVod.generateMediaSequences()];
|
|
123
|
+
case 2:
|
|
124
|
+
_a.sent();
|
|
125
|
+
_a.label = 3;
|
|
126
|
+
case 3: return [3 /*break*/, 5];
|
|
127
|
+
case 4:
|
|
128
|
+
hlsVod = currentVod;
|
|
129
|
+
_a.label = 5;
|
|
130
|
+
case 5:
|
|
120
131
|
this.cache.currentVod.ts = Date.now();
|
|
121
132
|
this.cache.currentVod.value = hlsVod;
|
|
122
133
|
return [2 /*return*/, hlsVod];
|
|
@@ -133,7 +144,7 @@ var SharedSessionState = /** @class */ (function () {
|
|
|
133
144
|
if (!this.sessionId) {
|
|
134
145
|
throw new Error("shared session state store has not been initialized");
|
|
135
146
|
}
|
|
136
|
-
if (!this.store.isShared()) return [3 /*break*/,
|
|
147
|
+
if (!this.store.isShared()) return [3 /*break*/, 8];
|
|
137
148
|
return [4 /*yield*/, this.store.clearLeaderCache()];
|
|
138
149
|
case 1:
|
|
139
150
|
_a.sent();
|
|
@@ -144,7 +155,7 @@ var SharedSessionState = /** @class */ (function () {
|
|
|
144
155
|
return [4 /*yield*/, this.set("currentVod", hlsVod.toJSON())];
|
|
145
156
|
case 3:
|
|
146
157
|
_a.sent();
|
|
147
|
-
return [3 /*break*/,
|
|
158
|
+
return [3 /*break*/, 7];
|
|
148
159
|
case 4:
|
|
149
160
|
debug("[".concat(this.sessionId, "]: Not a leader. Will not overwrite. Getting currentVod in shared store"));
|
|
150
161
|
return [4 /*yield*/, this.get("currentVod")];
|
|
@@ -152,13 +163,17 @@ var SharedSessionState = /** @class */ (function () {
|
|
|
152
163
|
currentVod = _a.sent();
|
|
153
164
|
hlsVod = new HLSVod();
|
|
154
165
|
hlsVod.fromJSON(currentVod);
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
case
|
|
158
|
-
case 8:
|
|
166
|
+
if (!hlsVod.skipSerializeMediaSequences) return [3 /*break*/, 7];
|
|
167
|
+
return [4 /*yield*/, hlsVod.generateMediaSequences()];
|
|
168
|
+
case 6:
|
|
159
169
|
_a.sent();
|
|
160
|
-
_a.label =
|
|
170
|
+
_a.label = 7;
|
|
171
|
+
case 7: return [3 /*break*/, 10];
|
|
172
|
+
case 8: return [4 /*yield*/, this.set("currentVod", hlsVod)];
|
|
161
173
|
case 9:
|
|
174
|
+
_a.sent();
|
|
175
|
+
_a.label = 10;
|
|
176
|
+
case 10:
|
|
162
177
|
if (this.cache.currentVod) {
|
|
163
178
|
this.cache.currentVod.ts = Date.now();
|
|
164
179
|
this.cache.currentVod.ttl = CURRENTVOD_CACHE_TTL;
|
package/dist/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eyevinn-channel-engine",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.3.0",
|
|
4
4
|
"description": "OTT TV Channel Engine",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"dependencies": {
|
|
31
31
|
"@eyevinn/hls-repeat": "^0.2.0",
|
|
32
32
|
"@eyevinn/hls-truncate": "^0.3.0",
|
|
33
|
-
"@eyevinn/hls-vodtolive": "^
|
|
33
|
+
"@eyevinn/hls-vodtolive": "^4.0.0",
|
|
34
34
|
"@eyevinn/m3u8": "^0.5.3",
|
|
35
35
|
"abort-controller": "^3.0.0",
|
|
36
36
|
"debug": "^3.2.7",
|
package/engine/server.ts
CHANGED
|
@@ -46,6 +46,7 @@ export interface ChannelEngineOpts {
|
|
|
46
46
|
subtitleSliceEndpoint?: string;
|
|
47
47
|
useVTTSubtitles?: boolean;
|
|
48
48
|
alwaysNewSegments?: boolean;
|
|
49
|
+
partialStoreHLSVod?: boolean;
|
|
49
50
|
alwaysMapBandwidthByNearest?: boolean;
|
|
50
51
|
diffCompensationRate?: number;
|
|
51
52
|
staticDirectory?: string;
|
|
@@ -183,6 +184,7 @@ export class ChannelEngine {
|
|
|
183
184
|
private subtitleSliceEndpoint: string;
|
|
184
185
|
private useVTTSubtitles: boolean;
|
|
185
186
|
private alwaysNewSegments: boolean;
|
|
187
|
+
private partialStoreHLSVod: boolean;
|
|
186
188
|
private alwaysMapBandwidthByNearest: boolean;
|
|
187
189
|
private defaultSlateUri?: string;
|
|
188
190
|
private slateDuration?: number;
|
|
@@ -223,6 +225,10 @@ export class ChannelEngine {
|
|
|
223
225
|
if (options && options.alwaysNewSegments) {
|
|
224
226
|
this.alwaysNewSegments = true;
|
|
225
227
|
}
|
|
228
|
+
this.partialStoreHLSVod = false;
|
|
229
|
+
if (options && options.partialStoreHLSVod) {
|
|
230
|
+
this.partialStoreHLSVod = true;
|
|
231
|
+
}
|
|
226
232
|
this.alwaysMapBandwidthByNearest = false;
|
|
227
233
|
if (options && options.alwaysMapBandwidthByNearest) {
|
|
228
234
|
this.alwaysMapBandwidthByNearest = true;
|
|
@@ -460,6 +466,7 @@ export class ChannelEngine {
|
|
|
460
466
|
subtitleSliceEndpoint: this.subtitleSliceEndpoint,
|
|
461
467
|
useVTTSubtitles: this.useVTTSubtitles,
|
|
462
468
|
alwaysNewSegments: options.alwaysNewSegments,
|
|
469
|
+
partialStoreHLSVod: options.partialStoreHLSVod,
|
|
463
470
|
alwaysMapBandwidthByNearest: options.alwaysMapBandwidthByNearest,
|
|
464
471
|
noSessionDataTags: options.noSessionDataTags,
|
|
465
472
|
playheadDiffThreshold: channel.options && channel.options.playheadDiffThreshold ? channel.options.playheadDiffThreshold : this.streamerOpts.defaultPlayheadDiffThreshold,
|
package/engine/session.js
CHANGED
|
@@ -73,11 +73,17 @@ class Session {
|
|
|
73
73
|
this.isAllowedToClearVodCache = null;
|
|
74
74
|
this.alwaysNewSegments = null;
|
|
75
75
|
this.alwaysMapBandwidthByNearest = null;
|
|
76
|
+
this.partialStoreHLSVod = null;
|
|
77
|
+
this.currentPlayheadRef = null;
|
|
76
78
|
if (config) {
|
|
77
79
|
if (config.alwaysNewSegments) {
|
|
78
80
|
this.alwaysNewSegments = config.alwaysNewSegments;
|
|
79
81
|
}
|
|
80
82
|
|
|
83
|
+
if (config.partialStoreHLSVod) {
|
|
84
|
+
this.partialStoreHLSVod = config.partialStoreHLSVod;
|
|
85
|
+
}
|
|
86
|
+
|
|
81
87
|
if (config.alwaysMapBandwidthByNearest) {
|
|
82
88
|
this.alwaysMapBandwidthByNearest = config.alwaysMapBandwidthByNearest;
|
|
83
89
|
}
|
|
@@ -637,7 +643,7 @@ class Session {
|
|
|
637
643
|
}
|
|
638
644
|
let currentVod = null;
|
|
639
645
|
const sessionState = await this._sessionState.getValues(["discSeqAudio", "vodMediaSeqAudio"]);
|
|
640
|
-
let playheadState = await this._playheadState.getValues(["mediaSeqAudio", "vodMediaSeqAudio"]);
|
|
646
|
+
let playheadState = await this._playheadState.getValues(["mediaSeqAudio", "vodMediaSeqAudio", "playheadRef"]);
|
|
641
647
|
|
|
642
648
|
if (playheadState.vodMediaSeqAudio > sessionState.vodMediaSeqAudio || (playheadState.vodMediaSeqAudio < sessionState.vodMediaSeqAudio && playheadState.mediaSeqAudio === this.prevMediaSeqOffset.audio)) {
|
|
643
649
|
const state = await this._sessionState.get("state");
|
|
@@ -658,14 +664,10 @@ class Session {
|
|
|
658
664
|
if (currentVod) {
|
|
659
665
|
// condition suggesting that a new vod should exist
|
|
660
666
|
if (playheadState.vodMediaSeqAudio < 2 || playheadState.mediaSeqAudio !== this.prevMediaSeqOffset.audio) {
|
|
661
|
-
|
|
662
|
-
let cacheAge = null;
|
|
663
|
-
if (this._sessionState.cache && this._sessionState.cache.currentVod.ts) {
|
|
664
|
-
cacheAge = Date.now() - this._sessionState.cache.currentVod.ts;
|
|
665
|
-
}
|
|
666
|
-
if (cacheAge !== null && cacheAge > AGE_THRESH) {
|
|
667
|
+
if (playheadState.playheadRef > this.currentPlayheadRef) {
|
|
667
668
|
await timer(500);
|
|
668
|
-
|
|
669
|
+
this.currentPlayheadRef = playheadState.playheadRef;
|
|
670
|
+
debug(`[${this._sessionId}]: While requesting audio manifest for ${audioGroupId}-${audioLanguage}, (mseq=${playheadState.vodMediaSeqAudio})`);
|
|
669
671
|
await this._sessionState.clearCurrentVodCache(); // force reading up from shared store
|
|
670
672
|
currentVod = await this._sessionState.getCurrentVod();
|
|
671
673
|
}
|
|
@@ -712,7 +714,7 @@ class Session {
|
|
|
712
714
|
}
|
|
713
715
|
let currentVod = null;
|
|
714
716
|
const sessionState = await this._sessionState.getValues(["discSeqSubtitle", "vodMediaSeqSubtitle"]);
|
|
715
|
-
let playheadState = await this._playheadState.getValues(["mediaSeqSubtitle", "vodMediaSeqSubtitle"]);
|
|
717
|
+
let playheadState = await this._playheadState.getValues(["mediaSeqSubtitle", "vodMediaSeqSubtitle", "playheadRef"]);
|
|
716
718
|
|
|
717
719
|
if (playheadState.vodMediaSeqSubtitle > sessionState.vodMediaSeqSubtitle || (playheadState.vodMediaSeqSubtitle < sessionState.vodMediaSeqSubtitle && playheadState.mediaSeqSubtitle === this.prevMediaSeqOffset.subtitle)) {
|
|
718
720
|
const state = await this._sessionState.get("state");
|
|
@@ -733,14 +735,10 @@ class Session {
|
|
|
733
735
|
if (currentVod) {
|
|
734
736
|
// condition suggesting that a new vod should exist
|
|
735
737
|
if (playheadState.vodMediaSeqSubtitle < 2 || playheadState.mediaSeqSubtitle !== this.prevMediaSeqOffset.subtitle) {
|
|
736
|
-
|
|
737
|
-
let cacheAge = null;
|
|
738
|
-
if (this._sessionState.cache && this._sessionState.cache.currentVod.ts) {
|
|
739
|
-
cacheAge = Date.now() - this._sessionState.cache.currentVod.ts;
|
|
740
|
-
}
|
|
741
|
-
if (cacheAge !== null && cacheAge > AGE_THRESH) {
|
|
738
|
+
if (playheadState.playheadRef > this.currentPlayheadRef) {
|
|
742
739
|
await timer(500);
|
|
743
|
-
|
|
740
|
+
this.currentPlayheadRef = playheadState.playheadRef;
|
|
741
|
+
debug(`[${this._sessionId}]: While requesting subtitle manifest for ${subtitleGroupId}-${subtitleLanguage}, (mseq=${playheadState.vodMediaSeqSubtitle})`);
|
|
744
742
|
await this._sessionState.clearCurrentVodCache(); // force reading up from shared store
|
|
745
743
|
currentVod = await this._sessionState.getCurrentVod();
|
|
746
744
|
}
|
|
@@ -1275,7 +1273,7 @@ class Session {
|
|
|
1275
1273
|
await this._sessionState.set("discSeq", sessionState.discSeq + lastDiscontinuity);
|
|
1276
1274
|
await this._sessionState.set("discSeqAudio", sessionState.discSeqAudio + lastDiscontinuityAudio);
|
|
1277
1275
|
await this._sessionState.set("slateCount", sessionState.slateCount + 1);
|
|
1278
|
-
await this._playheadState.set("playheadRef", Date.now(), isLeader);
|
|
1276
|
+
this.currentPlayheadRef = await this._playheadState.set("playheadRef", Date.now(), isLeader);
|
|
1279
1277
|
|
|
1280
1278
|
cloudWatchLog(!this.cloudWatchLogging, 'engine-session', { event: 'slateInserted', channel: this._sessionId });
|
|
1281
1279
|
|
|
@@ -1331,7 +1329,8 @@ class Session {
|
|
|
1331
1329
|
subtitleSliceEndpoint: this.subtitleSliceEndpoint,
|
|
1332
1330
|
shouldContainSubtitles: this.use_vtt_subtitles,
|
|
1333
1331
|
expectedSubtitleTracks: this._subtitleTracks,
|
|
1334
|
-
alwaysMapBandwidthByNearest: this.alwaysMapBandwidthByNearest
|
|
1332
|
+
alwaysMapBandwidthByNearest: this.alwaysMapBandwidthByNearest,
|
|
1333
|
+
skipSerializeMediaSequences: this.partialStoreHLSVod
|
|
1335
1334
|
};
|
|
1336
1335
|
newVod = new HLSVod(vodResponse.uri, [], vodResponse.unixTs, vodResponse.offset * 1000, m3u8Header(this._instanceId), hlsOpts);
|
|
1337
1336
|
if (vodResponse.timedMetadata) {
|
|
@@ -1375,7 +1374,6 @@ class Session {
|
|
|
1375
1374
|
sessionState.vodMediaSeqVideo = await this._sessionState.set("vodMediaSeqVideo", 0);
|
|
1376
1375
|
sessionState.vodMediaSeqAudio = await this._sessionState.set("vodMediaSeqAudio", 0);
|
|
1377
1376
|
sessionState.vodMediaSeqSubtitle = await this._sessionState.set("vodMediaSeqSubtitle", 0);
|
|
1378
|
-
await this._playheadState.set("playheadRef", Date.now(), isLeader);
|
|
1379
1377
|
this.produceEvent({
|
|
1380
1378
|
type: 'NOW_PLAYING',
|
|
1381
1379
|
data: {
|
|
@@ -1385,6 +1383,7 @@ class Session {
|
|
|
1385
1383
|
});
|
|
1386
1384
|
sessionState.state = await this._sessionState.set("state", SessionState.VOD_PLAYING);
|
|
1387
1385
|
sessionState.currentVod = await this._sessionState.setCurrentVod(currentVod, { ttl: currentVod.getDuration() * 1000 });
|
|
1386
|
+
this.currentPlayheadRef = await this._playheadState.set("playheadRef", Date.now(), isLeader);
|
|
1388
1387
|
await this._sessionState.remove("nextVod");
|
|
1389
1388
|
return;
|
|
1390
1389
|
} else {
|
|
@@ -1508,7 +1507,8 @@ class Session {
|
|
|
1508
1507
|
subtitleSliceEndpoint: this.subtitleSliceEndpoint,
|
|
1509
1508
|
shouldContainSubtitles: this.use_vtt_subtitles,
|
|
1510
1509
|
expectedSubtitleTracks: this._subtitleTracks,
|
|
1511
|
-
alwaysMapBandwidthByNearest: this.alwaysMapBandwidthByNearest
|
|
1510
|
+
alwaysMapBandwidthByNearest: this.alwaysMapBandwidthByNearest,
|
|
1511
|
+
skipSerializeMediaSequences: this.partialStoreHLSVod
|
|
1512
1512
|
};
|
|
1513
1513
|
newVod = new HLSVod(vodResponse.uri, null, vodResponse.unixTs, vodResponse.offset * 1000, m3u8Header(this._instanceId), hlsOpts);
|
|
1514
1514
|
if (vodResponse.timedMetadata) {
|
|
@@ -1560,7 +1560,7 @@ class Session {
|
|
|
1560
1560
|
currentVod = newVod;
|
|
1561
1561
|
debug(`[${this._sessionId}]: msequences=${currentVod.getLiveMediaSequencesCount()}; audio msequences=${currentVod.getLiveMediaSequencesCount("audio")}; subtitle msequences=${currentVod.getLiveMediaSequencesCount("subtitle")}`);
|
|
1562
1562
|
sessionState.currentVod = await this._sessionState.setCurrentVod(currentVod, { ttl: currentVod.getDuration() * 1000 });
|
|
1563
|
-
await this._playheadState.set("playheadRef", Date.now(), isLeader);
|
|
1563
|
+
this.currentPlayheadRef = await this._playheadState.set("playheadRef", Date.now(), isLeader);
|
|
1564
1564
|
sessionState.vodMediaSeqVideo = await this._sessionState.set("vodMediaSeqVideo", 0);
|
|
1565
1565
|
sessionState.vodMediaSeqAudio = await this._sessionState.set("vodMediaSeqAudio", 0);
|
|
1566
1566
|
sessionState.vodMediaSeqSubtitle = await this._sessionState.set("vodMediaSeqSubtitle", 0);
|
|
@@ -1675,7 +1675,7 @@ class Session {
|
|
|
1675
1675
|
await this._playheadState.set("vodMediaSeqVideo", 0, isLeader);
|
|
1676
1676
|
await this._playheadState.set("vodMediaSeqAudio", 0, isLeader);
|
|
1677
1677
|
await this._playheadState.set("vodMediaSeqSubtitle", 0, isLeader);
|
|
1678
|
-
await this._playheadState.set("playheadRef", Date.now(), isLeader);
|
|
1678
|
+
this.currentPlayheadRef = await this._playheadState.set("playheadRef", Date.now(), isLeader);
|
|
1679
1679
|
// 4) Log to debug and cloudwatch
|
|
1680
1680
|
debug(`[${this._sessionId}]: LEADER: Set new Reloaded VOD and vodMediaSeq counts in store.`);
|
|
1681
1681
|
debug(`[${this._sessionId}]: next VOD Reloaded (${currentVod.getDeltaTimes()})`);
|
|
@@ -1756,7 +1756,8 @@ class Session {
|
|
|
1756
1756
|
subtitleSliceEndpoint: this.subtitleSliceEndpoint,
|
|
1757
1757
|
shouldContainSubtitles: this.use_vtt_subtitles,
|
|
1758
1758
|
expectedSubtitleTracks: this._subtitleTracks,
|
|
1759
|
-
alwaysMapBandwidthByNearest: this.alwaysMapBandwidthByNearest
|
|
1759
|
+
alwaysMapBandwidthByNearest: this.alwaysMapBandwidthByNearest,
|
|
1760
|
+
skipSerializeMediaSequences: this.partialStoreHLSVod
|
|
1760
1761
|
};
|
|
1761
1762
|
const timestamp = Date.now();
|
|
1762
1763
|
hlsVod = new HLSVod(this.slateUri, null, timestamp, null, m3u8Header(this._instanceId), hlsOpts);
|
|
@@ -1860,7 +1861,8 @@ class Session {
|
|
|
1860
1861
|
subtitleSliceEndpoint: this.subtitleSliceEndpoint,
|
|
1861
1862
|
shouldContainSubtitles: this.use_vtt_subtitles,
|
|
1862
1863
|
expectedSubtitleTracks: this._subtitleTracks,
|
|
1863
|
-
alwaysMapBandwidthByNearest: this.alwaysMapBandwidthByNearest
|
|
1864
|
+
alwaysMapBandwidthByNearest: this.alwaysMapBandwidthByNearest,
|
|
1865
|
+
skipSerializeMediaSequences: this.partialStoreHLSVod
|
|
1864
1866
|
};
|
|
1865
1867
|
const timestamp = Date.now();
|
|
1866
1868
|
hlsVod = new HLSVod(nexVodUri, null, timestamp, null, m3u8Header(this._instanceId), hlsOpts);
|
package/engine/session_state.js
CHANGED
|
@@ -57,9 +57,18 @@ class SharedSessionState {
|
|
|
57
57
|
let hlsVod = null;
|
|
58
58
|
if (currentVod) {
|
|
59
59
|
if (this.store.isShared()) {
|
|
60
|
-
|
|
60
|
+
const strToMB = (str) => {
|
|
61
|
+
const bytesPerCharacter = 2; // Assuming each character takes around 2 bytes in memory
|
|
62
|
+
const stringSizeBytes = str.length * bytesPerCharacter;
|
|
63
|
+
const sizeInMegabytes = stringSizeBytes / (1024 * 1024);
|
|
64
|
+
return sizeInMegabytes.toFixed(1);
|
|
65
|
+
}
|
|
66
|
+
debug(`[${this.sessionId}]: reading ${currentVod.length} characters or (${strToMB(currentVod)} MB) from shared store (${Date.now()} < ${this.cache.currentVod.ts + this.cache.currentVod.ttl})`);
|
|
61
67
|
hlsVod = new HLSVod();
|
|
62
68
|
hlsVod.fromJSON(currentVod);
|
|
69
|
+
if (hlsVod.skipSerializeMediaSequences) {
|
|
70
|
+
await hlsVod.generateMediaSequences();
|
|
71
|
+
}
|
|
63
72
|
} else {
|
|
64
73
|
hlsVod = currentVod;
|
|
65
74
|
}
|
|
@@ -83,6 +92,9 @@ class SharedSessionState {
|
|
|
83
92
|
const currentVod = await this.get("currentVod");
|
|
84
93
|
hlsVod = new HLSVod();
|
|
85
94
|
hlsVod.fromJSON(currentVod);
|
|
95
|
+
if (hlsVod.skipSerializeMediaSequences) {
|
|
96
|
+
await hlsVod.generateMediaSequences();
|
|
97
|
+
}
|
|
86
98
|
}
|
|
87
99
|
} else {
|
|
88
100
|
await this.set("currentVod", hlsVod);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eyevinn-channel-engine",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.3.0",
|
|
4
4
|
"description": "OTT TV Channel Engine",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"dependencies": {
|
|
31
31
|
"@eyevinn/hls-repeat": "^0.2.0",
|
|
32
32
|
"@eyevinn/hls-truncate": "^0.3.0",
|
|
33
|
-
"@eyevinn/hls-vodtolive": "^
|
|
33
|
+
"@eyevinn/hls-vodtolive": "^4.0.0",
|
|
34
34
|
"@eyevinn/m3u8": "^0.5.3",
|
|
35
35
|
"abort-controller": "^3.0.0",
|
|
36
36
|
"debug": "^3.2.7",
|