eyevinn-channel-engine 4.0.5 → 4.0.6

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.
@@ -818,7 +818,7 @@ var ChannelEngine = /** @class */ (function () {
818
818
  "Access-Control-Allow-Origin": "*",
819
819
  "Access-Control-Allow-Headers": "X-Session-Id",
820
820
  "Access-Control-Expose-Headers": "X-Session-Id",
821
- "Cache-Control": "no-cache",
821
+ "Cache-Control": "max-age=300",
822
822
  "X-Session-Id": session.sessionId,
823
823
  "X-Instance-Id": this.instanceId + "<".concat(version, ">"),
824
824
  });
@@ -87,7 +87,7 @@ declare class Session {
87
87
  }>;
88
88
  getCurrentMediaManifestAsync(bw: any, playbackSessionId: any): Promise<any>;
89
89
  getCurrentAudioManifestAsync(audioGroupId: any, audioLanguage: any, playbackSessionId: any): Promise<any>;
90
- incrementAsync(incOpts: any): Promise<any>;
90
+ incrementAsync(): Promise<any>;
91
91
  getMediaManifestAsync(bw: any, opts: any): Promise<any>;
92
92
  getAudioManifestAsync(audioGroupId: any, audioLanguage: any, opts: any): Promise<any>;
93
93
  getMasterManifestAsync(filter: any): Promise<string>;
@@ -193,7 +193,7 @@ var Session = /** @class */ (function () {
193
193
  });
194
194
  Session.prototype.startPlayheadAsync = function () {
195
195
  return __awaiter(this, void 0, void 0, function () {
196
- var playheadState, state, numberOfLargeTicks, audioIncrement, tsIncrementBegin, manifest, tsIncrementEnd, sessionState, isLeader, firstDuration, tickInterval, reqTickInterval, timeSpentInIncrement, tickInterval, delta, position, currentVod, sessionState_1, posDiff, incrementValue, index, audioSeqLastIdx, thresh, direction, audioPosition, timePosition, diff, timeToAdd, timeToAdd, DIFF_COMPENSATION, changeMaxTick, tsTickEnd, lastDuration, nextTickInterval, err_1;
196
+ var playheadState, state, numberOfLargeTicks, audioIncrement, tsIncrementBegin, manifest, tsIncrementEnd, sessionState, isLeader, firstDuration, tickInterval, reqTickInterval, timeSpentInIncrement, tickInterval, delta, position, timePosition, diff, timeToAdd, timeToAdd, DIFF_COMPENSATION, changeMaxTick, tsTickEnd, lastDuration, nextTickInterval, err_1;
197
197
  return __generator(this, function (_a) {
198
198
  switch (_a.label) {
199
199
  case 0:
@@ -212,14 +212,12 @@ var Session = /** @class */ (function () {
212
212
  audioIncrement = 1;
213
213
  _a.label = 3;
214
214
  case 3:
215
- if (!(state !== PlayheadState.CRASHED)) return [3 /*break*/, 32];
215
+ if (!(state !== PlayheadState.CRASHED)) return [3 /*break*/, 25];
216
216
  _a.label = 4;
217
217
  case 4:
218
- _a.trys.push([4, 29, , 31]);
218
+ _a.trys.push([4, 22, , 24]);
219
219
  tsIncrementBegin = Date.now();
220
- return [4 /*yield*/, this.incrementAsync({
221
- audio: audioIncrement
222
- })];
220
+ return [4 /*yield*/, this.incrementAsync()];
223
221
  case 5:
224
222
  manifest = _a.sent();
225
223
  if (!!manifest) return [3 /*break*/, 7];
@@ -256,7 +254,7 @@ var Session = /** @class */ (function () {
256
254
  debug("[".concat(this._sessionId, "]: I am the leader and updated tick interval to ").concat(tickInterval, " sec"));
257
255
  cloudWatchLog(!this.cloudWatchLogging, 'engine-session', { event: 'tickIntervalUpdated', channel: this._sessionId, tickIntervalSec: tickInterval });
258
256
  this._playheadState.set("tickInterval", tickInterval);
259
- return [3 /*break*/, 28];
257
+ return [3 /*break*/, 21];
260
258
  case 13:
261
259
  if (!(state == PlayheadState.STOPPED)) return [3 /*break*/, 14];
262
260
  debug("[".concat(this._sessionId, "]: Stopping playhead"));
@@ -275,49 +273,6 @@ var Session = /** @class */ (function () {
275
273
  return [4 /*yield*/, this._getCurrentPlayheadPosition()];
276
274
  case 16:
277
275
  position = (_a.sent()) * 1000;
278
- if (!this.use_demuxed_audio) return [3 /*break*/, 23];
279
- return [4 /*yield*/, this._sessionState.getCurrentVod()];
280
- case 17:
281
- currentVod = _a.sent();
282
- return [4 /*yield*/, this._sessionState.getValues(["vodMediaSeqAudio"])];
283
- case 18:
284
- sessionState_1 = _a.sent();
285
- posDiff = void 0;
286
- incrementValue = 1;
287
- index = 0;
288
- audioSeqLastIdx = currentVod.getLiveMediaSequencesCount("audio") - 1;
289
- thresh = 0.5;
290
- direction = 0;
291
- _a.label = 19;
292
- case 19: return [4 /*yield*/, this._getAudioPlayheadPosition(sessionState_1.vodMediaSeqAudio + index)];
293
- case 20:
294
- audioPosition = (_a.sent()) * 1000;
295
- posDiff = position - audioPosition;
296
- if (posDiff > thresh && direction >= 0) {
297
- index++;
298
- incrementValue++;
299
- direction = 1;
300
- }
301
- else if (posDiff < -thresh && direction <= 0) {
302
- incrementValue = 0;
303
- index--;
304
- direction = -1;
305
- return [3 /*break*/, 22];
306
- }
307
- else if (direction > 0 && posDiff < 0) {
308
- return [3 /*break*/, 22];
309
- }
310
- if (sessionState_1.vodMediaSeqAudio + index > audioSeqLastIdx || sessionState_1.vodMediaSeqAudio + index < 0) {
311
- return [3 /*break*/, 22];
312
- }
313
- _a.label = 21;
314
- case 21:
315
- if (!(-thresh < posDiff && posDiff < thresh)) return [3 /*break*/, 19];
316
- _a.label = 22;
317
- case 22:
318
- audioIncrement = incrementValue;
319
- _a.label = 23;
320
- case 23:
321
276
  timePosition = Date.now() - playheadState.playheadRef;
322
277
  // Apply time position offset if set, only after external diff compensation has concluded.
323
278
  if (this.timePositionOffset && this.diffCompensation <= 0 && this.alwaysNewSegments) {
@@ -368,36 +323,36 @@ var Session = /** @class */ (function () {
368
323
  }
369
324
  debug("[".concat(this._sessionId, "]: (").concat((new Date()).toISOString(), ") ").concat(timeSpentInIncrement, "sec in increment. Next tick in ").concat(tickInterval, " seconds"));
370
325
  return [4 /*yield*/, timer((tickInterval * 1000) - 50)];
371
- case 24:
326
+ case 17:
372
327
  _a.sent();
373
328
  tsTickEnd = Date.now();
374
329
  return [4 /*yield*/, this._playheadState.set("tickMs", (tsTickEnd - tsIncrementBegin))];
375
- case 25:
330
+ case 18:
376
331
  _a.sent();
377
332
  cloudWatchLog(!this.cloudWatchLogging, 'engine-session', { event: 'tickInterval', channel: this._sessionId, tickTimeMs: (tsTickEnd - tsIncrementBegin) });
378
- if (!this.alwaysNewSegments) return [3 /*break*/, 28];
333
+ if (!this.alwaysNewSegments) return [3 /*break*/, 21];
379
334
  return [4 /*yield*/, this._getLastDuration(manifest)];
380
- case 26:
335
+ case 19:
381
336
  lastDuration = _a.sent();
382
337
  nextTickInterval = lastDuration < 2 ? 2 : lastDuration;
383
338
  return [4 /*yield*/, this._playheadState.set("tickInterval", nextTickInterval)];
384
- case 27:
339
+ case 20:
385
340
  _a.sent();
386
341
  cloudWatchLog(!this.cloudWatchLogging, "engine-session", { event: "tickIntervalUpdated", channel: this._sessionId, tickIntervalSec: nextTickInterval });
387
- _a.label = 28;
388
- case 28: return [3 /*break*/, 31];
389
- case 29:
342
+ _a.label = 21;
343
+ case 21: return [3 /*break*/, 24];
344
+ case 22:
390
345
  err_1 = _a.sent();
391
346
  debug("[".concat(this._sessionId, "]: Playhead consumer crashed (1)"));
392
347
  console.error("[".concat(this._sessionId, "]: ").concat(err_1.message));
393
348
  cloudWatchLog(!this.cloudWatchLogging, 'engine-session', { event: 'error', on: 'playhead', channel: this._sessionId, err: err_1 });
394
349
  debug(err_1);
395
350
  return [4 /*yield*/, this._playheadState.setState(PlayheadState.CRASHED)];
396
- case 30:
351
+ case 23:
397
352
  state = _a.sent();
398
- return [3 /*break*/, 31];
399
- case 31: return [3 /*break*/, 3];
400
- case 32: return [2 /*return*/];
353
+ return [3 /*break*/, 24];
354
+ case 24: return [3 /*break*/, 3];
355
+ case 25: return [2 /*return*/];
401
356
  }
402
357
  });
403
358
  });
@@ -786,7 +741,7 @@ var Session = /** @class */ (function () {
786
741
  };
787
742
  Session.prototype.getCurrentMediaManifestAsync = function (bw, playbackSessionId) {
788
743
  return __awaiter(this, void 0, void 0, function () {
789
- var tries, sessionState, playheadState, state, isLeader, diffMs, currentVod, manifestMseq, manifestDseq, mediaSequenceValue, m3u8_1, err_4;
744
+ var tries, sessionState, playheadState, state, DELAY_TIME_MS, ACTION, isLeader, diffMs, currentVod, manifestMseq, manifestDseq, mediaSequenceValue, m3u8_1, err_4;
790
745
  return __generator(this, function (_a) {
791
746
  switch (_a.label) {
792
747
  case 0:
@@ -815,29 +770,22 @@ var Session = /** @class */ (function () {
815
770
  if (this.prevMediaSeqOffset.video === null) {
816
771
  this.prevMediaSeqOffset.video = playheadState.mediaSeq;
817
772
  }
818
- if (!(playheadState.vodMediaSeqVideo > sessionState.vodMediaSeqVideo ||
819
- (playheadState.vodMediaSeqVideo < sessionState.vodMediaSeqVideo &&
820
- playheadState.mediaSeq === this.prevMediaSeqOffset.video))) return [3 /*break*/, 11];
773
+ if (!(playheadState.vodMediaSeqVideo > sessionState.vodMediaSeqVideo || (playheadState.vodMediaSeqVideo < sessionState.vodMediaSeqVideo && playheadState.mediaSeq === this.prevMediaSeqOffset.video))) return [3 /*break*/, 9];
821
774
  return [4 /*yield*/, this._sessionState.get("state")];
822
775
  case 6:
823
776
  state = _a.sent();
824
- if (![SessionState.VOD_RELOAD_INIT, SessionState.VOD_RELOAD_INITIATING].includes(state)) return [3 /*break*/, 9];
825
- debug("[".concat(this._sessionId, "]: Recently reloaded Vod. PlayheadState not up-to-date (").concat(playheadState.vodMediaSeqVideo, "_").concat(sessionState.vodMediaSeqVideo, "). Waiting 500ms before reading from store again"));
826
- return [4 /*yield*/, timer(500)];
777
+ DELAY_TIME_MS = 1000;
778
+ ACTION = [SessionState.VOD_RELOAD_INIT, SessionState.VOD_RELOAD_INITIATING].includes(state) ? "Reloaded" : "Loaded Next";
779
+ debug("[".concat(this._sessionId, "]: Recently ").concat(ACTION, " Vod. PlayheadState not up-to-date (").concat(playheadState.vodMediaSeqVideo, "_").concat(sessionState.vodMediaSeqVideo, "). Waiting ").concat(DELAY_TIME_MS, "ms before reading from store again"));
780
+ return [4 /*yield*/, timer(DELAY_TIME_MS)];
827
781
  case 7:
828
782
  _a.sent();
829
783
  return [4 /*yield*/, this._playheadState.getValues(["mediaSeq", "vodMediaSeqVideo"])];
830
784
  case 8:
831
785
  playheadState = _a.sent();
832
- return [3 /*break*/, 11];
786
+ _a.label = 9;
833
787
  case 9:
834
- debug("[".concat(this._sessionId, "]: Recently Loaded Next Vod. PlayheadState not up-to-date. Delay media-m3u8 Response by 1000ms"));
835
- return [4 /*yield*/, timer(1000)];
836
- case 10:
837
- _a.sent();
838
- _a.label = 11;
839
- case 11:
840
- if (!(playheadState.vodMediaSeqVideo < 2 || playheadState.mediaSeq !== this.prevMediaSeqOffset.video)) return [3 /*break*/, 16];
788
+ if (!(playheadState.vodMediaSeqVideo < 2 || playheadState.mediaSeq !== this.prevMediaSeqOffset.video)) return [3 /*break*/, 14];
841
789
  debug("[".concat(this._sessionId, "]: current[").concat(playheadState.vodMediaSeqVideo, "]_prev[").concat(this.prevVodMediaSeq.video, "]"));
842
790
  debug("[".concat(this._sessionId, "]: current-offset[").concat(playheadState.mediaSeq, "]_prev-offset[").concat(this.prevMediaSeqOffset.video, "]"));
843
791
  // If true, then we have not updated the prev-values and not cleared the cache yet.
@@ -845,16 +793,16 @@ var Session = /** @class */ (function () {
845
793
  this.isAllowedToClearVodCache = true;
846
794
  }
847
795
  return [4 /*yield*/, this._sessionStateStore.isLeader(this._instanceId)];
848
- case 12:
796
+ case 10:
849
797
  isLeader = _a.sent();
850
- if (!(!isLeader && this.isAllowedToClearVodCache)) return [3 /*break*/, 15];
798
+ if (!(!isLeader && this.isAllowedToClearVodCache)) return [3 /*break*/, 13];
851
799
  debug("[".concat(this._sessionId, "]: Not a leader and first|second media sequence in a VOD is requested. Invalidate cache to ensure having the correct VOD."));
852
800
  return [4 /*yield*/, this._sessionState.clearCurrentVodCache()];
853
- case 13:
801
+ case 11:
854
802
  _a.sent();
855
803
  this.isAllowedToClearVodCache = false;
856
804
  return [4 /*yield*/, this._playheadState.get("diffCompensation")];
857
- case 14:
805
+ case 12:
858
806
  diffMs = _a.sent();
859
807
  if (diffMs) {
860
808
  this.diffCompensation = diffMs;
@@ -867,18 +815,18 @@ var Session = /** @class */ (function () {
867
815
  this.timePositionOffset = 0;
868
816
  }
869
817
  }
818
+ _a.label = 13;
819
+ case 13: return [3 /*break*/, 15];
820
+ case 14:
821
+ this.isAllowedToClearVodCache = true;
870
822
  _a.label = 15;
871
- case 15: return [3 /*break*/, 17];
823
+ case 15: return [4 /*yield*/, this._sessionState.getCurrentVod()];
872
824
  case 16:
873
- this.isAllowedToClearVodCache = true;
874
- _a.label = 17;
875
- case 17: return [4 /*yield*/, this._sessionState.getCurrentVod()];
876
- case 18:
877
825
  currentVod = _a.sent();
878
- if (!currentVod) return [3 /*break*/, 23];
879
- _a.label = 19;
880
- case 19:
881
- _a.trys.push([19, 20, , 22]);
826
+ if (!currentVod) return [3 /*break*/, 21];
827
+ _a.label = 17;
828
+ case 17:
829
+ _a.trys.push([17, 18, , 20]);
882
830
  manifestMseq = playheadState.mediaSeq + playheadState.vodMediaSeqVideo;
883
831
  manifestDseq = sessionState.discSeq + currentVod.discontinuities[playheadState.vodMediaSeqVideo];
884
832
  if (currentVod.sequenceAlwaysContainNewSegments) {
@@ -892,23 +840,23 @@ var Session = /** @class */ (function () {
892
840
  this.prevVodMediaSeq.video = playheadState.vodMediaSeqVideo;
893
841
  this.prevMediaSeqOffset.video = playheadState.mediaSeq;
894
842
  return [2 /*return*/, m3u8_1];
895
- case 20:
843
+ case 18:
896
844
  err_4 = _a.sent();
897
845
  logerror(this._sessionId, err_4);
898
846
  return [4 /*yield*/, this._sessionState.clearCurrentVodCache()];
899
- case 21:
847
+ case 19:
900
848
  _a.sent(); // force reading up from shared store
901
849
  throw new Error("Failed to generate manifest: " + JSON.stringify(playheadState));
902
- case 22: return [3 /*break*/, 24];
903
- case 23: throw new Error("Engine not ready");
904
- case 24: return [2 /*return*/];
850
+ case 20: return [3 /*break*/, 22];
851
+ case 21: throw new Error("Engine not ready");
852
+ case 22: return [2 /*return*/];
905
853
  }
906
854
  });
907
855
  });
908
856
  };
909
857
  Session.prototype.getCurrentAudioManifestAsync = function (audioGroupId, audioLanguage, playbackSessionId) {
910
858
  return __awaiter(this, void 0, void 0, function () {
911
- var currentVod, sessionState, playheadState, state, AGE_THRESH, cacheAge, manifestMseq, manifestDseq, mediaSequenceValue, m3u8_2, err_5;
859
+ var currentVod, sessionState, playheadState, state, DELAY_TIME_MS, ACTION, AGE_THRESH, cacheAge, manifestMseq, manifestDseq, mediaSequenceValue, m3u8_2, err_5;
912
860
  return __generator(this, function (_a) {
913
861
  switch (_a.label) {
914
862
  case 0:
@@ -922,30 +870,21 @@ var Session = /** @class */ (function () {
922
870
  return [4 /*yield*/, this._playheadState.getValues(["mediaSeqAudio", "vodMediaSeqAudio"])];
923
871
  case 2:
924
872
  playheadState = _a.sent();
925
- if (!(playheadState.vodMediaSeqAudio > sessionState.vodMediaSeqAudio ||
926
- (playheadState.vodMediaSeqAudio < sessionState.vodMediaSeqAudio && playheadState.mediaSeqAudio === this.prevMediaSeqOffset.audio))) return [3 /*break*/, 9];
873
+ if (!(playheadState.vodMediaSeqAudio > sessionState.vodMediaSeqAudio || (playheadState.vodMediaSeqAudio < sessionState.vodMediaSeqAudio && playheadState.mediaSeqAudio === this.prevMediaSeqOffset.audio))) return [3 /*break*/, 6];
927
874
  return [4 /*yield*/, this._sessionState.get("state")];
928
875
  case 3:
929
876
  state = _a.sent();
930
- if (![SessionState.VOD_RELOAD_INIT, SessionState.VOD_RELOAD_INITIATING].includes(state)) return [3 /*break*/, 6];
931
- debug("[".concat(this._sessionId, "]: Recently reloaded Vod. PlayheadState not up-to-date (").concat(playheadState.vodMediaSeqAudio, "_").concat(sessionState.vodMediaSeqAudio, ") AUDIO. Waiting 500ms before reading from store again"));
932
- return [4 /*yield*/, timer(500)];
877
+ DELAY_TIME_MS = 1000;
878
+ ACTION = [SessionState.VOD_RELOAD_INIT, SessionState.VOD_RELOAD_INITIATING].includes(state) ? "Reloaded" : "Loaded Next";
879
+ debug("[".concat(this._sessionId, "]: Recently ").concat(ACTION, " Vod. PlayheadState not up-to-date (").concat(playheadState.vodMediaSeqAudio, "_").concat(sessionState.vodMediaSeqAudio, "). Waiting ").concat(DELAY_TIME_MS, "ms before reading from store again"));
880
+ return [4 /*yield*/, timer(DELAY_TIME_MS)];
933
881
  case 4:
934
882
  _a.sent();
935
883
  return [4 /*yield*/, this._playheadState.getValues(["mediaSeqAudio", "vodMediaSeqAudio"])];
936
884
  case 5:
937
885
  playheadState = _a.sent();
938
- return [3 /*break*/, 9];
886
+ _a.label = 6;
939
887
  case 6:
940
- debug("[".concat(this._sessionId, "]: Recently Loaded Next Vod. PlayheadState not up-to-date. Delay audio-m3u8 Response by 1000ms"));
941
- return [4 /*yield*/, timer(1000)];
942
- case 7:
943
- _a.sent();
944
- return [4 /*yield*/, this._playheadState.getValues(["mediaSeqAudio", "vodMediaSeqAudio"])];
945
- case 8:
946
- playheadState = _a.sent();
947
- _a.label = 9;
948
- case 9:
949
888
  // local store the prev values
950
889
  if (this.prevVodMediaSeq.audio === null) {
951
890
  this.prevVodMediaSeq.audio = playheadState.vodMediaSeqAudio;
@@ -954,29 +893,29 @@ var Session = /** @class */ (function () {
954
893
  this.prevMediaSeqOffset.audio = playheadState.mediaSeqAudio;
955
894
  }
956
895
  return [4 /*yield*/, this._sessionState.getCurrentVod()];
957
- case 10:
896
+ case 7:
958
897
  currentVod = _a.sent();
959
- if (!currentVod) return [3 /*break*/, 18];
960
- if (!(playheadState.vodMediaSeqAudio < 2 || playheadState.mediaSeqAudio !== this.prevMediaSeqOffset.audio)) return [3 /*break*/, 14];
961
- AGE_THRESH = 20 * 1000;
898
+ if (!currentVod) return [3 /*break*/, 15];
899
+ if (!(playheadState.vodMediaSeqAudio < 2 || playheadState.mediaSeqAudio !== this.prevMediaSeqOffset.audio)) return [3 /*break*/, 11];
900
+ AGE_THRESH = this.averageSegmentDuration * 2;
962
901
  cacheAge = null;
963
902
  if (this._sessionState.cache && this._sessionState.cache.currentVod.ts) {
964
903
  cacheAge = Date.now() - this._sessionState.cache.currentVod.ts;
965
904
  }
966
- if (!(cacheAge !== null && cacheAge > AGE_THRESH)) return [3 /*break*/, 14];
905
+ if (!(cacheAge !== null && cacheAge > AGE_THRESH)) return [3 /*break*/, 11];
967
906
  return [4 /*yield*/, timer(500)];
968
- case 11:
907
+ case 8:
969
908
  _a.sent();
970
909
  debug("[".concat(this._sessionId, "]: While requesting audio manifest for ").concat(audioGroupId, "-").concat(audioLanguage, ", (mseq=").concat(playheadState.vodMediaSeqAudio, ")(vod cache age=").concat(cacheAge, ")"));
971
910
  return [4 /*yield*/, this._sessionState.clearCurrentVodCache()];
972
- case 12:
911
+ case 9:
973
912
  _a.sent(); // force reading up from shared store
974
913
  return [4 /*yield*/, this._sessionState.getCurrentVod()];
975
- case 13:
914
+ case 10:
976
915
  currentVod = _a.sent();
977
- _a.label = 14;
978
- case 14:
979
- _a.trys.push([14, 15, , 17]);
916
+ _a.label = 11;
917
+ case 11:
918
+ _a.trys.push([11, 12, , 14]);
980
919
  manifestMseq = playheadState.mediaSeqAudio + playheadState.vodMediaSeqAudio;
981
920
  manifestDseq = sessionState.discSeqAudio + currentVod.discontinuitiesAudio[playheadState.vodMediaSeqAudio];
982
921
  if (currentVod.sequenceAlwaysContainNewSegments) {
@@ -994,23 +933,23 @@ var Session = /** @class */ (function () {
994
933
  this.prevVodMediaSeq.audio = playheadState.vodMediaSeqAudio;
995
934
  this.prevMediaSeqOffset.audio = playheadState.mediaSeqAudio;
996
935
  return [2 /*return*/, m3u8_2];
997
- case 15:
936
+ case 12:
998
937
  err_5 = _a.sent();
999
938
  logerror(this._sessionId, err_5);
1000
939
  return [4 /*yield*/, this._sessionState.clearCurrentVodCache()];
1001
- case 16:
940
+ case 13:
1002
941
  _a.sent(); // force reading up from shared store
1003
942
  throw new Error("Failed to generate audio manifest: " + JSON.stringify(playheadState));
1004
- case 17: return [3 /*break*/, 19];
1005
- case 18: throw new Error("Engine not ready");
1006
- case 19: return [2 /*return*/];
943
+ case 14: return [3 /*break*/, 16];
944
+ case 15: throw new Error("Engine not ready");
945
+ case 16: return [2 /*return*/];
1007
946
  }
1008
947
  });
1009
948
  });
1010
949
  };
1011
- Session.prototype.incrementAsync = function (incOpts) {
950
+ Session.prototype.incrementAsync = function () {
1012
951
  return __awaiter(this, void 0, void 0, function () {
1013
- var isLeader, sessionState, playheadState, currentVod, _a, leaderAction, _b, m3u8_3, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, mediaSequenceValue, diffMs, m3u8;
952
+ var isLeader, sessionState, playheadState, currentVod, _a, leaderAction, _b, m3u8_3, _c, audioIncrement, position, currentVod_1, sessionState_1, posDiff, incrementValue, index, audioSeqLastIdx, thresh, audioPosition, _d, _e, _f, _g, _h, _j, _k, _l, _m, mediaSequenceValue, diffMs, m3u8;
1014
953
  return __generator(this, function (_o) {
1015
954
  switch (_o.label) {
1016
955
  case 0: return [4 /*yield*/, this._tickAsync()];
@@ -1070,82 +1009,124 @@ var Session = /** @class */ (function () {
1070
1009
  }
1071
1010
  this.isAllowedToClearVodCache = true;
1072
1011
  _o.label = 13;
1073
- case 13: return [3 /*break*/, 17];
1012
+ case 13: return [3 /*break*/, 25];
1074
1013
  case 14:
1075
1014
  _c = sessionState;
1076
1015
  return [4 /*yield*/, this._sessionState.increment("vodMediaSeqVideo")];
1077
1016
  case 15:
1078
1017
  _c.vodMediaSeqVideo = _o.sent();
1079
- if (!incOpts) return [3 /*break*/, 17];
1080
- _d = sessionState;
1081
- return [4 /*yield*/, this._sessionState.increment("vodMediaSeqAudio", incOpts.audio)];
1018
+ audioIncrement = void 0;
1019
+ if (!this.use_demuxed_audio) return [3 /*break*/, 23];
1020
+ return [4 /*yield*/, this._getCurrentPlayheadPosition()];
1082
1021
  case 16:
1083
- _d.vodMediaSeqAudio = _o.sent();
1084
- _o.label = 17;
1022
+ position = (_o.sent()) * 1000;
1023
+ return [4 /*yield*/, this._sessionState.getCurrentVod()];
1085
1024
  case 17:
1086
- if (!(sessionState.vodMediaSeqVideo >= currentVod.getLiveMediaSequencesCount() - 1)) return [3 /*break*/, 20];
1025
+ currentVod_1 = _o.sent();
1026
+ return [4 /*yield*/, this._sessionState.getValues(["vodMediaSeqAudio"])];
1027
+ case 18:
1028
+ sessionState_1 = _o.sent();
1029
+ posDiff = void 0;
1030
+ incrementValue = 1;
1031
+ index = 0;
1032
+ audioSeqLastIdx = currentVod_1.getLiveMediaSequencesCount("audio") - 1;
1033
+ thresh = 0.5;
1034
+ _o.label = 19;
1035
+ case 19: return [4 /*yield*/, this._getAudioPlayheadPosition(sessionState_1.vodMediaSeqAudio + index)];
1036
+ case 20:
1037
+ audioPosition = (_o.sent()) * 1000;
1038
+ posDiff = position - audioPosition;
1039
+ if (posDiff < 0) {
1040
+ return [3 /*break*/, 22];
1041
+ }
1042
+ if (posDiff > thresh) {
1043
+ index++;
1044
+ incrementValue++;
1045
+ }
1046
+ else {
1047
+ index = incrementValue;
1048
+ return [3 /*break*/, 22];
1049
+ }
1050
+ if (sessionState_1.vodMediaSeqAudio + index > audioSeqLastIdx) {
1051
+ return [3 /*break*/, 22];
1052
+ }
1053
+ _o.label = 21;
1054
+ case 21:
1055
+ if (!(-thresh < posDiff && posDiff < thresh)) return [3 /*break*/, 19];
1056
+ _o.label = 22;
1057
+ case 22:
1058
+ audioIncrement = index;
1059
+ _o.label = 23;
1060
+ case 23:
1061
+ _d = sessionState;
1062
+ return [4 /*yield*/, this._sessionState.increment("vodMediaSeqAudio", audioIncrement)];
1063
+ case 24:
1064
+ _d.vodMediaSeqAudio = _o.sent();
1065
+ _o.label = 25;
1066
+ case 25:
1067
+ if (!(sessionState.vodMediaSeqVideo >= currentVod.getLiveMediaSequencesCount() - 1)) return [3 /*break*/, 28];
1087
1068
  _e = sessionState;
1088
1069
  return [4 /*yield*/, this._sessionState.set("vodMediaSeqVideo", currentVod.getLiveMediaSequencesCount() - 1)];
1089
- case 18:
1070
+ case 26:
1090
1071
  _e.vodMediaSeqVideo = _o.sent();
1091
1072
  _f = sessionState;
1092
1073
  return [4 /*yield*/, this._sessionState.set("state", SessionState.VOD_NEXT_INIT)];
1093
- case 19:
1074
+ case 27:
1094
1075
  _f.state = _o.sent();
1095
- _o.label = 20;
1096
- case 20:
1097
- if (!(sessionState.vodMediaSeqAudio >= currentVod.getLiveMediaSequencesCount("audio") - 1)) return [3 /*break*/, 22];
1076
+ _o.label = 28;
1077
+ case 28:
1078
+ if (!(sessionState.vodMediaSeqAudio >= currentVod.getLiveMediaSequencesCount("audio") - 1)) return [3 /*break*/, 30];
1098
1079
  _g = sessionState;
1099
1080
  return [4 /*yield*/, this._sessionState.set("vodMediaSeqAudio", currentVod.getLiveMediaSequencesCount("audio") - 1)];
1100
- case 21:
1081
+ case 29:
1101
1082
  _g.vodMediaSeqAudio = _o.sent();
1102
- _o.label = 22;
1103
- case 22:
1104
- if (!this.isSwitchingBackToV2L) return [3 /*break*/, 24];
1083
+ _o.label = 30;
1084
+ case 30:
1085
+ if (!this.isSwitchingBackToV2L) return [3 /*break*/, 32];
1105
1086
  _h = sessionState;
1106
1087
  return [4 /*yield*/, this._sessionState.set("state", SessionState.VOD_RELOAD_INIT)];
1107
- case 23:
1088
+ case 31:
1108
1089
  _h.state = _o.sent();
1109
1090
  this.isSwitchingBackToV2L = false;
1110
- _o.label = 24;
1111
- case 24:
1091
+ _o.label = 32;
1092
+ case 32:
1112
1093
  _j = playheadState;
1113
1094
  return [4 /*yield*/, this._playheadState.set("mediaSeq", sessionState.mediaSeq)];
1114
- case 25:
1095
+ case 33:
1115
1096
  _j.mediaSeq = _o.sent();
1116
1097
  _k = playheadState;
1117
1098
  return [4 /*yield*/, this._playheadState.set("mediaSeqAudio", sessionState.mediaSeqAudio)];
1118
- case 26:
1099
+ case 34:
1119
1100
  _k.mediaSeqAudio = _o.sent();
1120
1101
  _l = playheadState;
1121
1102
  return [4 /*yield*/, this._playheadState.set("vodMediaSeqVideo", sessionState.vodMediaSeqVideo)];
1122
- case 27:
1103
+ case 35:
1123
1104
  _l.vodMediaSeqVideo = _o.sent();
1124
1105
  _m = playheadState;
1125
1106
  return [4 /*yield*/, this._playheadState.set("vodMediaSeqAudio", sessionState.vodMediaSeqAudio)];
1126
- case 28:
1107
+ case 36:
1127
1108
  _m.vodMediaSeqAudio = _o.sent();
1128
1109
  if (currentVod.sequenceAlwaysContainNewSegments) {
1129
1110
  mediaSequenceValue = currentVod.mediaSequenceValues[playheadState.vodMediaSeqVideo];
1130
1111
  debug("[".concat(this._sessionId, "]: Session can now serve mseq={").concat(playheadState.mediaSeq + mediaSequenceValue, "}"));
1131
1112
  }
1132
1113
  debug("[".concat(this._sessionId, "]: INCREMENT (mseq=").concat(playheadState.mediaSeq + playheadState.vodMediaSeqVideo, ") vodMediaSeq=(").concat(playheadState.vodMediaSeqVideo, "_").concat(playheadState.vodMediaSeqAudio, " of ").concat(currentVod.getLiveMediaSequencesCount(), "_").concat(currentVod.getLiveMediaSequencesCount("audio"), ")"));
1133
- if (!(playheadState.vodMediaSeqVideo < 2 || playheadState.mediaSeq !== this.prevMediaSeqOffset.video)) return [3 /*break*/, 33];
1114
+ if (!(playheadState.vodMediaSeqVideo < 2 || playheadState.mediaSeq !== this.prevMediaSeqOffset.video)) return [3 /*break*/, 41];
1134
1115
  debug("[".concat(this._sessionId, "]: current[").concat(playheadState.vodMediaSeqVideo, "]_prev[").concat(this.prevVodMediaSeq.video, "]"));
1135
1116
  debug("[".concat(this._sessionId, "]: current-offset[").concat(playheadState.mediaSeq, "]_prev-offset[").concat(this.prevMediaSeqOffset.video, "]"));
1136
1117
  if (playheadState.vodMediaSeqVideo < this.prevVodMediaSeq.video || playheadState.mediaSeq !== this.prevMediaSeqOffset.video) {
1137
1118
  this.isAllowedToClearVodCache = true;
1138
1119
  }
1139
- if (!(!isLeader && this.isAllowedToClearVodCache)) return [3 /*break*/, 32];
1120
+ if (!(!isLeader && this.isAllowedToClearVodCache)) return [3 /*break*/, 40];
1140
1121
  debug("[".concat(this._sessionId, "]: Not a leader and have just set 'playheadState.vodMediaSeqVideo' to 0|1. Invalidate cache to ensure having the correct VOD."));
1141
1122
  return [4 /*yield*/, this._sessionState.clearCurrentVodCache()];
1142
- case 29:
1123
+ case 37:
1143
1124
  _o.sent();
1144
1125
  return [4 /*yield*/, this._sessionState.getCurrentVod()];
1145
- case 30:
1126
+ case 38:
1146
1127
  currentVod = _o.sent();
1147
1128
  return [4 /*yield*/, this._playheadState.get("diffCompensation")];
1148
- case 31:
1129
+ case 39:
1149
1130
  diffMs = _o.sent();
1150
1131
  if (diffMs) {
1151
1132
  this.diffCompensation = diffMs;
@@ -1159,12 +1140,12 @@ var Session = /** @class */ (function () {
1159
1140
  }
1160
1141
  }
1161
1142
  this.isAllowedToClearVodCache = false;
1162
- _o.label = 32;
1163
- case 32: return [3 /*break*/, 34];
1164
- case 33:
1143
+ _o.label = 40;
1144
+ case 40: return [3 /*break*/, 42];
1145
+ case 41:
1165
1146
  this.isAllowedToClearVodCache = true;
1166
- _o.label = 34;
1167
- case 34:
1147
+ _o.label = 42;
1148
+ case 42:
1168
1149
  // Update Value for Previous Sequence
1169
1150
  this.prevVodMediaSeq.video = playheadState.vodMediaSeqVideo;
1170
1151
  this.prevMediaSeqOffset.video = playheadState.mediaSeq;
@@ -1174,7 +1155,7 @@ var Session = /** @class */ (function () {
1174
1155
  }
1175
1156
  m3u8 = currentVod.getLiveMediaSequences(playheadState.mediaSeq, 180000, playheadState.vodMediaSeqVideo, sessionState.discSeq);
1176
1157
  return [4 /*yield*/, this._playheadState.setLastM3u8(m3u8)];
1177
- case 35:
1158
+ case 43:
1178
1159
  _o.sent();
1179
1160
  return [2 /*return*/, m3u8];
1180
1161
  }
@@ -1537,7 +1518,7 @@ var Session = /** @class */ (function () {
1537
1518
  };
1538
1519
  Session.prototype._tickAsync = function () {
1539
1520
  return __awaiter(this, void 0, void 0, function () {
1540
- var newVod, sessionState, isLeader, currentVod, vodResponse, _a, nextVodPromise, nextVodStart, _b, loadPromise, hlsOpts, loadStart, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, err_6, _o, length_1, endMseqValue, endMseqValueAudio, lastDiscontinuity, lastDiscontinuityAudio, _p, vodPromise, gracePeriod, nextVodStart, _q, loadPromise, hlsOpts, loadStart, _r, _s, _t, _u, _v, _w, _x, _y, _z, diffMs, err_7, startTS, _0, mSeq, currentVod_1, dSeq, mSeqOffset, reloadBehind, segments, playheadState, nextMseq, _1, err_8;
1521
+ var newVod, sessionState, isLeader, currentVod, vodResponse, _a, nextVodPromise, nextVodStart, _b, loadPromise, hlsOpts, loadStart, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, err_6, _o, length_1, endMseqValue, endMseqValueAudio, lastDiscontinuity, lastDiscontinuityAudio, _p, vodPromise, gracePeriod, nextVodStart, _q, loadPromise, hlsOpts, loadStart, _r, _s, _t, _u, _v, _w, _x, _y, _z, diffMs, err_7, startTS, _0, mSeq, currentVod_2, dSeq, mSeqOffset, reloadBehind, segments, playheadState, nextMseq, _1, err_8;
1541
1522
  var _this = this;
1542
1523
  return __generator(this, function (_2) {
1543
1524
  switch (_2.label) {
@@ -1962,8 +1943,8 @@ var Session = /** @class */ (function () {
1962
1943
  mSeq = this.switchDataForSession.mediaSeq;
1963
1944
  return [4 /*yield*/, this._sessionState.getCurrentVod()];
1964
1945
  case 64:
1965
- currentVod_1 = _2.sent();
1966
- if (currentVod_1.sequenceAlwaysContainNewSegments) {
1946
+ currentVod_2 = _2.sent();
1947
+ if (currentVod_2.sequenceAlwaysContainNewSegments) {
1967
1948
  // (!) will need to compensate if using this setting on HLSVod Object.
1968
1949
  Object.keys(this.switchDataForSession.transitionSegments).forEach(function (bw) {
1969
1950
  var shiftedSeg = _this.switchDataForSession.transitionSegments[bw].shift();
@@ -1997,19 +1978,19 @@ var Session = /** @class */ (function () {
1997
1978
  case 68:
1998
1979
  playheadState = _2.sent();
1999
1980
  nextMseq = playheadState.vodMediaSeqVideo + 1;
2000
- if (nextMseq > currentVod_1.getLiveMediaSequencesCount() - 1) {
2001
- nextMseq = currentVod_1.getLiveMediaSequencesCount() - 1;
1981
+ if (nextMseq > currentVod_2.getLiveMediaSequencesCount() - 1) {
1982
+ nextMseq = currentVod_2.getLiveMediaSequencesCount() - 1;
2002
1983
  }
2003
1984
  // ---------------------------------------------------.
2004
1985
  // TODO: Support reloading with audioSegments as well |
2005
1986
  // ---------------------------------------------------'
2006
- return [4 /*yield*/, currentVod_1.reload(nextMseq, segments, null, reloadBehind)];
1987
+ return [4 /*yield*/, currentVod_2.reload(nextMseq, segments, null, reloadBehind)];
2007
1988
  case 69:
2008
1989
  // ---------------------------------------------------.
2009
1990
  // TODO: Support reloading with audioSegments as well |
2010
1991
  // ---------------------------------------------------'
2011
1992
  _2.sent();
2012
- return [4 /*yield*/, this._sessionState.setCurrentVod(currentVod_1, { ttl: currentVod_1.getDuration() * 1000 })];
1993
+ return [4 /*yield*/, this._sessionState.setCurrentVod(currentVod_2, { ttl: currentVod_2.getDuration() * 1000 })];
2013
1994
  case 70:
2014
1995
  _2.sent();
2015
1996
  return [4 /*yield*/, this._sessionState.set("vodReloaded", 1)];
@@ -2032,9 +2013,9 @@ var Session = /** @class */ (function () {
2032
2013
  _2.sent();
2033
2014
  // 4) Log to debug and cloudwatch
2034
2015
  debug("[".concat(this._sessionId, "]: LEADER: Set new Reloaded VOD and vodMediaSeq counts in store."));
2035
- debug("[".concat(this._sessionId, "]: next VOD Reloaded (").concat(currentVod_1.getDeltaTimes(), ")"));
2036
- debug("[".concat(this._sessionId, "]: ").concat(currentVod_1.getPlayheadPositions()));
2037
- debug("[".concat(this._sessionId, "]: msequences=").concat(currentVod_1.getLiveMediaSequencesCount()));
2016
+ debug("[".concat(this._sessionId, "]: next VOD Reloaded (").concat(currentVod_2.getDeltaTimes(), ")"));
2017
+ debug("[".concat(this._sessionId, "]: ").concat(currentVod_2.getPlayheadPositions()));
2018
+ debug("[".concat(this._sessionId, "]: msequences=").concat(currentVod_2.getLiveMediaSequencesCount()));
2038
2019
  cloudWatchLog(!this.cloudWatchLogging, "engine-session", { event: "switchback", channel: this._sessionId, reqTimeMs: Date.now() - startTS });
2039
2020
  return [2 /*return*/];
2040
2021
  case 77:
@@ -2334,6 +2315,9 @@ var Session = /** @class */ (function () {
2334
2315
  case 1:
2335
2316
  currentVod = _a.sent();
2336
2317
  playheadPositions = currentVod.getPlayheadPositions("audio");
2318
+ if (seqIdx >= playheadPositions.length - 1) {
2319
+ seqIdx = playheadPositions.length - 1;
2320
+ }
2337
2321
  debug("[".concat(this._sessionId, "]: Current audio playhead position (").concat(seqIdx, "): ").concat(playheadPositions[seqIdx]));
2338
2322
  return [2 /*return*/, playheadPositions[seqIdx]];
2339
2323
  }
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eyevinn-channel-engine",
3
- "version": "4.0.5",
3
+ "version": "4.0.6",
4
4
  "description": "OTT TV Channel Engine",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
package/engine/server.ts CHANGED
@@ -659,7 +659,7 @@ export class ChannelEngine {
659
659
  "Access-Control-Allow-Origin": "*",
660
660
  "Access-Control-Allow-Headers": "X-Session-Id",
661
661
  "Access-Control-Expose-Headers": "X-Session-Id",
662
- "Cache-Control": "no-cache",
662
+ "Cache-Control": "max-age=300",
663
663
  "X-Session-Id": session.sessionId,
664
664
  "X-Instance-Id": this.instanceId + `<${version}>`,
665
665
  });
package/engine/session.js CHANGED
@@ -160,9 +160,7 @@ class Session {
160
160
  while (state !== PlayheadState.CRASHED) {
161
161
  try {
162
162
  const tsIncrementBegin = Date.now();
163
- const manifest = await this.incrementAsync({
164
- audio: audioIncrement
165
- });
163
+ const manifest = await this.incrementAsync();
166
164
  if (!manifest) {
167
165
  debug(`[${this._sessionId}]: No manifest available yet, will try again after 1000ms`);
168
166
  await timer(1000);
@@ -202,38 +200,6 @@ class Session {
202
200
  debug(`[${this._sessionId}]: Delta time is != 0 need will adjust ${delta}sec to tick interval. tick=${tickInterval}`);
203
201
  }
204
202
  const position = (await this._getCurrentPlayheadPosition()) * 1000;
205
-
206
- if (this.use_demuxed_audio) {
207
- let currentVod = await this._sessionState.getCurrentVod();
208
- const sessionState = await this._sessionState.getValues(["vodMediaSeqAudio"]);
209
- let posDiff;
210
- let incrementValue = 1;
211
- let index = 0;
212
- const audioSeqLastIdx = currentVod.getLiveMediaSequencesCount("audio") - 1;
213
- const thresh = 0.5;
214
- let direction = 0;
215
- do {
216
- const audioPosition = (await this._getAudioPlayheadPosition(sessionState.vodMediaSeqAudio + index)) * 1000;
217
- posDiff = position - audioPosition;
218
- if (posDiff > thresh && direction >= 0) {
219
- index++;
220
- incrementValue++;
221
- direction = 1;
222
- } else if (posDiff < -thresh && direction <= 0) {
223
- incrementValue = 0;
224
- index--;
225
- direction = -1;
226
- break;
227
- } else if (direction > 0 && posDiff < 0) {
228
- break;
229
- }
230
- if (sessionState.vodMediaSeqAudio + index > audioSeqLastIdx || sessionState.vodMediaSeqAudio + index < 0) {
231
- break;
232
- }
233
- } while (!(-thresh < posDiff && posDiff < thresh));
234
- audioIncrement = incrementValue;
235
- }
236
-
237
203
  let timePosition = Date.now() - playheadState.playheadRef;
238
204
  // Apply time position offset if set, only after external diff compensation has concluded.
239
205
  if (this.timePositionOffset && this.diffCompensation <= 0 && this.alwaysNewSegments) {
@@ -576,18 +542,13 @@ class Session {
576
542
  this.prevMediaSeqOffset.video = playheadState.mediaSeq;
577
543
  }
578
544
 
579
- if (playheadState.vodMediaSeqVideo > sessionState.vodMediaSeqVideo ||
580
- (playheadState.vodMediaSeqVideo < sessionState.vodMediaSeqVideo &&
581
- playheadState.mediaSeq === this.prevMediaSeqOffset.video)) {
545
+ if (playheadState.vodMediaSeqVideo > sessionState.vodMediaSeqVideo || (playheadState.vodMediaSeqVideo < sessionState.vodMediaSeqVideo && playheadState.mediaSeq === this.prevMediaSeqOffset.video)) {
582
546
  const state = await this._sessionState.get("state");
583
- if ([SessionState.VOD_RELOAD_INIT, SessionState.VOD_RELOAD_INITIATING].includes(state)) {
584
- debug(`[${this._sessionId}]: Recently reloaded Vod. PlayheadState not up-to-date (${playheadState.vodMediaSeqVideo}_${sessionState.vodMediaSeqVideo}). Waiting 500ms before reading from store again`);
585
- await timer(500);
586
- playheadState = await this._playheadState.getValues(["mediaSeq", "vodMediaSeqVideo"]);
587
- } else {
588
- debug(`[${this._sessionId}]: Recently Loaded Next Vod. PlayheadState not up-to-date. Delay media-m3u8 Response by 1000ms`);
589
- await timer(1000);
590
- }
547
+ const DELAY_TIME_MS = 1000;
548
+ const ACTION = [SessionState.VOD_RELOAD_INIT, SessionState.VOD_RELOAD_INITIATING].includes(state) ? "Reloaded" : "Loaded Next";
549
+ debug(`[${this._sessionId}]: Recently ${ACTION} Vod. PlayheadState not up-to-date (${playheadState.vodMediaSeqVideo}_${sessionState.vodMediaSeqVideo}). Waiting ${DELAY_TIME_MS}ms before reading from store again`);
550
+ await timer(DELAY_TIME_MS);
551
+ playheadState = await this._playheadState.getValues(["mediaSeq", "vodMediaSeqVideo"]);
591
552
  }
592
553
 
593
554
  // Force reading up from store, but only once if the condition is right
@@ -655,24 +616,14 @@ class Session {
655
616
  const sessionState = await this._sessionState.getValues(["discSeqAudio", "vodMediaSeqAudio"]);
656
617
  let playheadState = await this._playheadState.getValues(["mediaSeqAudio", "vodMediaSeqAudio"]);
657
618
 
658
- if (
659
- playheadState.vodMediaSeqAudio > sessionState.vodMediaSeqAudio ||
660
- (playheadState.vodMediaSeqAudio < sessionState.vodMediaSeqAudio && playheadState.mediaSeqAudio === this.prevMediaSeqOffset.audio)
661
- ) {
619
+ if (playheadState.vodMediaSeqAudio > sessionState.vodMediaSeqAudio || (playheadState.vodMediaSeqAudio < sessionState.vodMediaSeqAudio && playheadState.mediaSeqAudio === this.prevMediaSeqOffset.audio)) {
662
620
  const state = await this._sessionState.get("state");
663
- if ([SessionState.VOD_RELOAD_INIT, SessionState.VOD_RELOAD_INITIATING].includes(state)) {
664
- debug(
665
- `[${this._sessionId}]: Recently reloaded Vod. PlayheadState not up-to-date (${playheadState.vodMediaSeqAudio}_${sessionState.vodMediaSeqAudio}) AUDIO. Waiting 500ms before reading from store again`
666
- );
667
- await timer(500);
668
- playheadState = await this._playheadState.getValues(["mediaSeqAudio", "vodMediaSeqAudio"]);
669
- } else {
670
- debug(`[${this._sessionId}]: Recently Loaded Next Vod. PlayheadState not up-to-date. Delay audio-m3u8 Response by 1000ms`);
671
- await timer(1000);
672
- playheadState = await this._playheadState.getValues(["mediaSeqAudio", "vodMediaSeqAudio"]);
673
- }
621
+ const DELAY_TIME_MS = 1000;
622
+ const ACTION = [SessionState.VOD_RELOAD_INIT, SessionState.VOD_RELOAD_INITIATING].includes(state) ? "Reloaded" : "Loaded Next";
623
+ debug(`[${this._sessionId}]: Recently ${ACTION} Vod. PlayheadState not up-to-date (${playheadState.vodMediaSeqAudio}_${sessionState.vodMediaSeqAudio}). Waiting ${DELAY_TIME_MS}ms before reading from store again`);
624
+ await timer(DELAY_TIME_MS);
625
+ playheadState = await this._playheadState.getValues(["mediaSeqAudio", "vodMediaSeqAudio"]);
674
626
  }
675
-
676
627
  // local store the prev values
677
628
  if (this.prevVodMediaSeq.audio === null) {
678
629
  this.prevVodMediaSeq.audio = playheadState.vodMediaSeqAudio;
@@ -684,7 +635,7 @@ class Session {
684
635
  if (currentVod) {
685
636
  // condition suggesting that a new vod should exist
686
637
  if (playheadState.vodMediaSeqAudio < 2 || playheadState.mediaSeqAudio !== this.prevMediaSeqOffset.audio) {
687
- const AGE_THRESH = 20 * 1000;
638
+ const AGE_THRESH = this.averageSegmentDuration * 2;
688
639
  let cacheAge = null;
689
640
  if (this._sessionState.cache && this._sessionState.cache.currentVod.ts) {
690
641
  cacheAge = Date.now() - this._sessionState.cache.currentVod.ts;
@@ -732,7 +683,7 @@ class Session {
732
683
  }
733
684
  }
734
685
 
735
- async incrementAsync(incOpts) {
686
+ async incrementAsync() {
736
687
  await this._tickAsync();
737
688
  const isLeader = await this._sessionStateStore.isLeader(this._instanceId);
738
689
 
@@ -772,9 +723,36 @@ class Session {
772
723
  }
773
724
  } else {
774
725
  sessionState.vodMediaSeqVideo = await this._sessionState.increment("vodMediaSeqVideo");
775
- if (incOpts) {
776
- sessionState.vodMediaSeqAudio = await this._sessionState.increment("vodMediaSeqAudio", incOpts.audio);
726
+ let audioIncrement;
727
+ if (this.use_demuxed_audio) {
728
+ const position = (await this._getCurrentPlayheadPosition()) * 1000;
729
+ let currentVod = await this._sessionState.getCurrentVod();
730
+ const sessionState = await this._sessionState.getValues(["vodMediaSeqAudio"]);
731
+ let posDiff;
732
+ let incrementValue = 1;
733
+ let index = 0;
734
+ const audioSeqLastIdx = currentVod.getLiveMediaSequencesCount("audio") - 1;
735
+ const thresh = 0.5;
736
+ do {
737
+ const audioPosition = (await this._getAudioPlayheadPosition(sessionState.vodMediaSeqAudio + index)) * 1000;
738
+ posDiff = position - audioPosition;
739
+ if (posDiff < 0) {
740
+ break;
741
+ }
742
+ if (posDiff > thresh) {
743
+ index++;
744
+ incrementValue++;
745
+ } else {
746
+ index = incrementValue;
747
+ break;
748
+ }
749
+ if (sessionState.vodMediaSeqAudio + index > audioSeqLastIdx) {
750
+ break;
751
+ }
752
+ } while (!(-thresh < posDiff && posDiff < thresh));
753
+ audioIncrement = index;
777
754
  }
755
+ sessionState.vodMediaSeqAudio = await this._sessionState.increment("vodMediaSeqAudio", audioIncrement);
778
756
  }
779
757
 
780
758
  if (sessionState.vodMediaSeqVideo >= currentVod.getLiveMediaSequencesCount() - 1) {
@@ -1691,6 +1669,9 @@ class Session {
1691
1669
  async _getAudioPlayheadPosition(seqIdx) {
1692
1670
  const currentVod = await this._sessionState.getCurrentVod();
1693
1671
  const playheadPositions = currentVod.getPlayheadPositions("audio");
1672
+ if (seqIdx >= playheadPositions.length - 1) {
1673
+ seqIdx = playheadPositions.length - 1
1674
+ }
1694
1675
  debug(`[${this._sessionId}]: Current audio playhead position (${seqIdx}): ${playheadPositions[seqIdx]}`);
1695
1676
  return playheadPositions[seqIdx];
1696
1677
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eyevinn-channel-engine",
3
- "version": "4.0.5",
3
+ "version": "4.0.6",
4
4
  "description": "OTT TV Channel Engine",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",