eyevinn-channel-engine 4.3.7 → 4.3.9

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.
@@ -123,4 +123,9 @@ declare class Session {
123
123
  _getLastDuration(manifest: any): Promise<any>;
124
124
  _getPlayheadDiffCompensationValue(diffMs: any, thresholdMs: any): number;
125
125
  _isOldVod(refTs: any, vodDur: any): boolean;
126
+ _determineExtraMediaIncrement(_extraType: any, _currentPosVideo: any, _extraSeqFinalIndex: any, _vodMediaSeqExtra: any, _getExtraPlayheadPositionAsyncFn: any): Promise<{
127
+ increment: number;
128
+ position: number;
129
+ diff: string;
130
+ }>;
126
131
  }
@@ -1087,24 +1087,24 @@ var Session = /** @class */ (function () {
1087
1087
  };
1088
1088
  Session.prototype.incrementAsync = function () {
1089
1089
  return __awaiter(this, void 0, void 0, function () {
1090
- var isLeader, sessionState, playheadState, currentVod, _a, isOldVod, nextState, leaderAction, leaderState, _b, m3u8_4, _c, audioIncrement, positionV, positionA, position, currentVod_1, sessionState_1, posDiff, incrementValue, index, audioSeqLastIdx, thresh, maxAcceptableDiff, audioPosition, _d, _e, newSessionState, updatedValues, updatedPlayhead, mediaSequenceValue, audioInfo, mediaSequenceValueAudio, diffMs, m3u8;
1091
- return __generator(this, function (_f) {
1092
- switch (_f.label) {
1090
+ var isLeader, sessionState, playheadState, currentVod, _a, isOldVod, nextState, leaderAction, leaderState, _b, m3u8_4, _c, playheadPosVideoMs, playheadAudio, playheadSubtitle, audioSeqLastIdx, sessionStateObj, _d, playheadPosVideo, _e, subtitleSeqLastIdx, sessionStateObj, _f, newSessionState, updatedValues, updatedPlayhead, mediaSequenceValue, audioInfo, mediaSequenceValueAudio, subsInfo, mediaSequenceValueSubtitle, diffMs, m3u8;
1091
+ return __generator(this, function (_g) {
1092
+ switch (_g.label) {
1093
1093
  case 0: return [4 /*yield*/, this._tickAsync()];
1094
1094
  case 1:
1095
- _f.sent();
1095
+ _g.sent();
1096
1096
  return [4 /*yield*/, this._sessionStateStore.isLeader(this._instanceId)];
1097
1097
  case 2:
1098
- isLeader = _f.sent();
1098
+ isLeader = _g.sent();
1099
1099
  return [4 /*yield*/, this._sessionState.getValues(["state", "mediaSeq", "mediaSeqAudio", "mediaSeqSubtitle", "discSeq", "discSeqAudio", "discSeqSubtitle", "vodMediaSeqVideo", "vodMediaSeqAudio", "vodMediaSeqSubtitle"])];
1100
1100
  case 3:
1101
- sessionState = _f.sent();
1101
+ sessionState = _g.sent();
1102
1102
  return [4 /*yield*/, this._playheadState.getValues(["mediaSeq", "mediaSeqAudio", "mediaSeqSubtitle", "vodMediaSeqVideo", "vodMediaSeqAudio", "vodMediaSubtitle", "playheadRef"])];
1103
1103
  case 4:
1104
- playheadState = _f.sent();
1104
+ playheadState = _g.sent();
1105
1105
  return [4 /*yield*/, this._sessionState.getCurrentVod()];
1106
1106
  case 5:
1107
- currentVod = _f.sent();
1107
+ currentVod = _g.sent();
1108
1108
  if (!(!currentVod ||
1109
1109
  sessionState.vodMediaSeqVideo === null ||
1110
1110
  sessionState.vodMediaSeqAudio === null ||
@@ -1116,14 +1116,14 @@ var Session = /** @class */ (function () {
1116
1116
  debug(sessionState);
1117
1117
  return [4 /*yield*/, this._sessionState.clearCurrentVodCache()];
1118
1118
  case 6:
1119
- _f.sent();
1119
+ _g.sent();
1120
1120
  if (!isLeader) return [3 /*break*/, 8];
1121
1121
  debug("[".concat(this._sessionId, "]: I am the leader, trying to initiate the session"));
1122
1122
  _a = sessionState;
1123
1123
  return [4 /*yield*/, this._sessionState.set("state", SessionState.VOD_INIT)];
1124
1124
  case 7:
1125
- _a.state = _f.sent();
1126
- _f.label = 8;
1125
+ _a.state = _g.sent();
1126
+ _g.label = 8;
1127
1127
  case 8: return [2 /*return*/, null];
1128
1128
  case 9:
1129
1129
  if (!(sessionState.state === SessionState.VOD_NEXT_INITIATING || sessionState.state === SessionState.VOD_RELOAD_INITIATING)) return [3 /*break*/, 14];
@@ -1139,13 +1139,13 @@ var Session = /** @class */ (function () {
1139
1139
  _b = sessionState;
1140
1140
  return [4 /*yield*/, this._sessionState.set("state", nextState)];
1141
1141
  case 10:
1142
- _b.state = _f.sent();
1142
+ _b.state = _g.sent();
1143
1143
  return [3 /*break*/, 13];
1144
1144
  case 11:
1145
1145
  debug("[".concat(this._sessionId, "]: Return the last generated m3u8 to give the leader some time"));
1146
1146
  return [4 /*yield*/, this._playheadState.getLastM3u8()];
1147
1147
  case 12:
1148
- m3u8_4 = _f.sent();
1148
+ m3u8_4 = _g.sent();
1149
1149
  if (m3u8_4) {
1150
1150
  return [2 /*return*/, m3u8_4];
1151
1151
  }
@@ -1153,78 +1153,65 @@ var Session = /** @class */ (function () {
1153
1153
  debug("[".concat(this._sessionId, "]: We don't have any previously generated m3u8"));
1154
1154
  }
1155
1155
  this.isAllowedToClearVodCache = true;
1156
- _f.label = 13;
1157
- case 13: return [3 /*break*/, 26];
1156
+ _g.label = 13;
1157
+ case 13: return [3 /*break*/, 28];
1158
1158
  case 14:
1159
1159
  _c = sessionState;
1160
1160
  return [4 /*yield*/, this._sessionState.increment("vodMediaSeqVideo", 1)];
1161
1161
  case 15:
1162
- _c.vodMediaSeqVideo = _f.sent();
1163
- audioIncrement = void 0;
1164
- if (!this.use_demuxed_audio) return [3 /*break*/, 23];
1165
- positionV = 0;
1166
- positionA = 0;
1162
+ _c.vodMediaSeqVideo = _g.sent();
1163
+ playheadPosVideoMs = void 0;
1164
+ playheadAudio = void 0;
1165
+ playheadSubtitle = void 0;
1166
+ if (!(this.use_demuxed_audio || this.use_vtt_subtitles)) return [3 /*break*/, 17];
1167
1167
  return [4 /*yield*/, this._getCurrentPlayheadPosition()];
1168
1168
  case 16:
1169
- position = (_f.sent()) * 1000;
1170
- positionV = position ? position / 1000 : 0;
1171
- return [4 /*yield*/, this._sessionState.getCurrentVod()];
1169
+ playheadPosVideoMs = (_g.sent()) * 1000;
1170
+ _g.label = 17;
1172
1171
  case 17:
1173
- currentVod_1 = _f.sent();
1172
+ if (!this.use_demuxed_audio) return [3 /*break*/, 21];
1173
+ audioSeqLastIdx = currentVod.getLiveMediaSequencesCount("audio") - 1;
1174
1174
  return [4 /*yield*/, this._sessionState.getValues(["vodMediaSeqAudio"])];
1175
1175
  case 18:
1176
- sessionState_1 = _f.sent();
1177
- posDiff = void 0;
1178
- incrementValue = 1;
1179
- index = 0;
1180
- audioSeqLastIdx = currentVod_1.getLiveMediaSequencesCount("audio") - 1;
1181
- thresh = 0.5;
1182
- maxAcceptableDiff = 0.001;
1183
- debug("[".concat(this._sessionId, "]: About to determine audio increment"));
1184
- _f.label = 19;
1185
- case 19: return [4 /*yield*/, this._getAudioPlayheadPosition(sessionState_1.vodMediaSeqAudio + index)];
1176
+ sessionStateObj = _g.sent();
1177
+ return [4 /*yield*/, this._determineExtraMediaIncrement("audio", playheadPosVideoMs, audioSeqLastIdx, sessionStateObj.vodMediaSeqAudio, this._getAudioPlayheadPosition.bind(this))];
1178
+ case 19:
1179
+ playheadAudio = _g.sent();
1180
+ // Perform the Increment
1181
+ debug("[".concat(this._sessionId, "]: Will increment audio with ").concat(playheadAudio.increment));
1182
+ _d = sessionState;
1183
+ return [4 /*yield*/, this._sessionState.increment("vodMediaSeqAudio", playheadAudio.increment)];
1186
1184
  case 20:
1187
- audioPosition = (_f.sent()) * 1000;
1188
- positionA = audioPosition ? audioPosition / 1000 : 0;
1189
- posDiff = (positionV - positionA).toFixed(3);
1190
- debug("[".concat(this._sessionId, "]: positionV=").concat(positionV, ";positionA=").concat(positionA, ";posDiff=").concat(posDiff));
1191
- if (posDiff <= maxAcceptableDiff) {
1192
- return [3 /*break*/, 22];
1193
- }
1194
- if (posDiff > thresh) {
1195
- index++;
1196
- incrementValue++;
1197
- }
1198
- else if (posDiff > maxAcceptableDiff) {
1199
- index = incrementValue;
1200
- debug("[".concat(this._sessionId, "]: Audio Stepping index set to = ").concat(index));
1201
- return [3 /*break*/, 22];
1202
- }
1203
- if (sessionState_1.vodMediaSeqAudio + index > audioSeqLastIdx) {
1204
- return [3 /*break*/, 22];
1205
- }
1206
- _f.label = 21;
1185
+ _d.vodMediaSeqAudio = _g.sent();
1186
+ _g.label = 21;
1207
1187
  case 21:
1208
- if (!(-thresh < posDiff && posDiff < thresh) && !isNaN(posDiff)) return [3 /*break*/, 19];
1209
- _f.label = 22;
1188
+ if (!this.use_vtt_subtitles) return [3 /*break*/, 27];
1189
+ _e = playheadPosVideo;
1190
+ if (_e) return [3 /*break*/, 23];
1191
+ return [4 /*yield*/, this._getCurrentPlayheadPosition()];
1210
1192
  case 22:
1211
- audioIncrement = index;
1212
- debug("[".concat(this._sessionId, "]: Current VOD Playhead Positions are to be: [").concat(positionV.toFixed(3), "][").concat(positionA.toFixed(3), "] (").concat(posDiff, ")"));
1213
- _f.label = 23;
1193
+ _e = (_g.sent()) * 1000;
1194
+ _g.label = 23;
1214
1195
  case 23:
1215
- debug("[".concat(this._sessionId, "]: Will increment audio with ").concat(audioIncrement));
1216
- _d = sessionState;
1217
- return [4 /*yield*/, this._sessionState.increment("vodMediaSeqAudio", audioIncrement)];
1196
+ playheadPosVideo = _e;
1197
+ subtitleSeqLastIdx = currentVod.getLiveMediaSequencesCount("subtitle") - 1;
1198
+ return [4 /*yield*/, this._sessionState.getValues(["vodMediaSeqSubtitle"])];
1218
1199
  case 24:
1219
- _d.vodMediaSeqAudio = _f.sent();
1220
- if (!this.use_vtt_subtitles) return [3 /*break*/, 26];
1221
- debug("[".concat(this._sessionId, "]: Will increment subtitle with 1"));
1222
- _e = sessionState;
1223
- return [4 /*yield*/, this._sessionState.increment("vodMediaSeqSubtitle", 1)];
1200
+ sessionStateObj = _g.sent();
1201
+ return [4 /*yield*/, this._determineExtraMediaIncrement("subtitle", playheadPosVideoMs, subtitleSeqLastIdx, sessionStateObj.vodMediaSeqSubtitle, this._getSubtitlePlayheadPosition.bind(this))];
1224
1202
  case 25:
1225
- _e.vodMediaSeqSubtitle = _f.sent();
1226
- _f.label = 26;
1203
+ playheadSubtitle = _g.sent();
1204
+ // Perform the Increment
1205
+ debug("[".concat(this._sessionId, "]: Will increment subtitle with ").concat(playheadSubtitle.increment));
1206
+ _f = sessionState;
1207
+ return [4 /*yield*/, this._sessionState.increment("vodMediaSeqSubtitle", playheadSubtitle.increment)];
1227
1208
  case 26:
1209
+ _f.vodMediaSeqSubtitle = _g.sent();
1210
+ _g.label = 27;
1211
+ case 27:
1212
+ debug("[".concat(this._sessionId, "]: Current VOD Playhead Positions are to be V[").concat((playheadPosVideoMs / 1000).toFixed(3), "]").concat(playheadAudio ? "A[".concat((playheadAudio.position).toFixed(3), "]") : "").concat(playheadSubtitle ? "S[".concat((playheadSubtitle.position).toFixed(3), ")]") : "").concat(playheadAudio ? " (".concat(playheadAudio.diff, ")") : "").concat(playheadSubtitle ? " (".concat(playheadSubtitle.diff, ")") : ""));
1213
+ _g.label = 28;
1214
+ case 28:
1228
1215
  newSessionState = {};
1229
1216
  if (sessionState.vodMediaSeqVideo >= currentVod.getLiveMediaSequencesCount() - 1) {
1230
1217
  newSessionState.vodMediaSeqVideo = currentVod.getLiveMediaSequencesCount() - 1;
@@ -1241,8 +1228,8 @@ var Session = /** @class */ (function () {
1241
1228
  this.isSwitchingBackToV2L = false;
1242
1229
  }
1243
1230
  return [4 /*yield*/, this._sessionState.setValues(newSessionState)];
1244
- case 27:
1245
- updatedValues = _f.sent();
1231
+ case 29:
1232
+ updatedValues = _g.sent();
1246
1233
  sessionState = __assign(__assign({}, sessionState), updatedValues);
1247
1234
  if (isLeader) {
1248
1235
  debug("[".concat(this._sessionId, "]: I am the leader, updating PlayheadState values"));
@@ -1255,8 +1242,8 @@ var Session = /** @class */ (function () {
1255
1242
  "vodMediaSeqAudio": sessionState.vodMediaSeqAudio,
1256
1243
  "vodMediaSeqSubtitle": sessionState.vodMediaSeqSubtitle
1257
1244
  }, isLeader)];
1258
- case 28:
1259
- updatedPlayhead = _f.sent();
1245
+ case 30:
1246
+ updatedPlayhead = _g.sent();
1260
1247
  playheadState = __assign(__assign({}, playheadState), updatedPlayhead);
1261
1248
  if (currentVod.sequenceAlwaysContainNewSegments) {
1262
1249
  mediaSequenceValue = currentVod.mediaSequenceValues[playheadState.vodMediaSeqVideo];
@@ -1265,26 +1252,31 @@ var Session = /** @class */ (function () {
1265
1252
  mediaSequenceValueAudio = currentVod.mediaSequenceValuesAudio[playheadState.vodMediaSeqAudio];
1266
1253
  audioInfo = " mseq[A]={".concat(playheadState.mediaSeqAudio + mediaSequenceValueAudio, "}");
1267
1254
  }
1268
- debug("[".concat(this._sessionId, "]: Session can now serve mseq[V]={").concat(playheadState.mediaSeq + mediaSequenceValue, "}") + audioInfo);
1255
+ subsInfo = "";
1256
+ if (this.use_vtt_subtitles) {
1257
+ mediaSequenceValueSubtitle = currentVod.mediaSequenceValuesSubtitle[playheadState.vodMediaSeqSubtitle];
1258
+ subsInfo = " mseq[S]={".concat(playheadState.mediaSeqSubtitle + mediaSequenceValueSubtitle, "}");
1259
+ }
1260
+ debug("[".concat(this._sessionId, "]: Session can now serve mseq[V]={").concat(playheadState.mediaSeq + mediaSequenceValue, "}") + audioInfo + subsInfo);
1269
1261
  }
1270
- 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"), ")"));
1271
- if (!(playheadState.vodMediaSeqVideo < 2 || playheadState.mediaSeq !== this.prevMediaSeqOffset.video)) return [3 /*break*/, 33];
1262
+ debug("[".concat(this._sessionId, "]: INCREMENT (mseq=").concat(playheadState.mediaSeq + playheadState.vodMediaSeqVideo, ") vodMediaSeq=(").concat(playheadState.vodMediaSeqVideo, "_").concat(playheadState.vodMediaSeqAudio).concat(this.use_vtt_subtitles ? "_".concat(playheadState.vodMediaSeqSubtitle) : "", " of ").concat(currentVod.getLiveMediaSequencesCount(), "_").concat(currentVod.getLiveMediaSequencesCount("audio")).concat(this.use_vtt_subtitles ? "_".concat(currentVod.getLiveMediaSequencesCount("subtitle"), ")") : ")"));
1263
+ if (!(playheadState.vodMediaSeqVideo < 2 || playheadState.mediaSeq !== this.prevMediaSeqOffset.video)) return [3 /*break*/, 35];
1272
1264
  debug("[".concat(this._sessionId, "]: current[").concat(playheadState.vodMediaSeqVideo, "]_prev[").concat(this.prevVodMediaSeq.video, "]"));
1273
1265
  debug("[".concat(this._sessionId, "]: current-offset[").concat(playheadState.mediaSeq, "]_prev-offset[").concat(this.prevMediaSeqOffset.video, "]"));
1274
1266
  if (playheadState.vodMediaSeqVideo < this.prevVodMediaSeq.video || playheadState.mediaSeq !== this.prevMediaSeqOffset.video) {
1275
1267
  this.isAllowedToClearVodCache = true;
1276
1268
  }
1277
- if (!(!isLeader && this.isAllowedToClearVodCache)) return [3 /*break*/, 32];
1269
+ if (!(!isLeader && this.isAllowedToClearVodCache)) return [3 /*break*/, 34];
1278
1270
  debug("[".concat(this._sessionId, "]: Not a leader and have just set 'playheadState.vodMediaSeqVideo' to 0|1. Invalidate cache to ensure having the correct VOD."));
1279
1271
  return [4 /*yield*/, this._sessionState.clearCurrentVodCache()];
1280
- case 29:
1281
- _f.sent();
1272
+ case 31:
1273
+ _g.sent();
1282
1274
  return [4 /*yield*/, this._sessionState.getCurrentVod()];
1283
- case 30:
1284
- currentVod = _f.sent();
1275
+ case 32:
1276
+ currentVod = _g.sent();
1285
1277
  return [4 /*yield*/, this._playheadState.get("diffCompensation")];
1286
- case 31:
1287
- diffMs = _f.sent();
1278
+ case 33:
1279
+ diffMs = _g.sent();
1288
1280
  if (diffMs) {
1289
1281
  this.diffCompensation = diffMs;
1290
1282
  debug("[".concat(this._sessionId, "]: Setting diffCompensation->").concat(this.diffCompensation));
@@ -1297,12 +1289,12 @@ var Session = /** @class */ (function () {
1297
1289
  }
1298
1290
  }
1299
1291
  this.isAllowedToClearVodCache = false;
1300
- _f.label = 32;
1301
- case 32: return [3 /*break*/, 34];
1302
- case 33:
1292
+ _g.label = 34;
1293
+ case 34: return [3 /*break*/, 36];
1294
+ case 35:
1303
1295
  this.isAllowedToClearVodCache = true;
1304
- _f.label = 34;
1305
- case 34:
1296
+ _g.label = 36;
1297
+ case 36:
1306
1298
  // Update Value for Previous Sequence
1307
1299
  this.prevVodMediaSeq.video = playheadState.vodMediaSeqVideo;
1308
1300
  this.prevMediaSeqOffset.video = playheadState.mediaSeq;
@@ -1316,8 +1308,8 @@ var Session = /** @class */ (function () {
1316
1308
  }
1317
1309
  m3u8 = currentVod.getLiveMediaSequences(playheadState.mediaSeq, 180000, playheadState.vodMediaSeqVideo, sessionState.discSeq);
1318
1310
  return [4 /*yield*/, this._playheadState.setLastM3u8(m3u8)];
1319
- case 35:
1320
- _f.sent();
1311
+ case 37:
1312
+ _g.sent();
1321
1313
  return [2 /*return*/, m3u8];
1322
1314
  }
1323
1315
  });
@@ -1325,7 +1317,7 @@ var Session = /** @class */ (function () {
1325
1317
  };
1326
1318
  Session.prototype.getMediaManifestAsync = function (bw, opts) {
1327
1319
  return __awaiter(this, void 0, void 0, function () {
1328
- var tsLastRequestVideo, timeSinceLastRequest, sessionState, currentVod, _a, sequencesToIncrement, _b, _c, _d, m3u8, lastM3u8, _e, _f, _g, tsLastRequestVideo_1, timeSinceLastRequest_1, sessionState_2, _h, lastM3u8_1, _j, _k, _l;
1320
+ var tsLastRequestVideo, timeSinceLastRequest, sessionState, currentVod, _a, sequencesToIncrement, _b, _c, _d, m3u8, lastM3u8, _e, _f, _g, tsLastRequestVideo_1, timeSinceLastRequest_1, sessionState_1, _h, lastM3u8_1, _j, _k, _l;
1329
1321
  return __generator(this, function (_m) {
1330
1322
  switch (_m.label) {
1331
1323
  case 0: // this function is no longer used and should be removed comment added 5/5-2023
@@ -1407,38 +1399,38 @@ var Session = /** @class */ (function () {
1407
1399
  timeSinceLastRequest_1 = (tsLastRequestVideo_1 === null) ? 0 : Date.now() - tsLastRequestVideo_1;
1408
1400
  return [4 /*yield*/, this._sessionState.getValues(["state", "vodMediaSeqVideo", "mediaSeq", "discSeq", "lastM3u8"])];
1409
1401
  case 17:
1410
- sessionState_2 = _m.sent();
1411
- if (!(sessionState_2.state === SessionState.VOD_NEXT_INITIATING)) return [3 /*break*/, 19];
1412
- _h = sessionState_2;
1402
+ sessionState_1 = _m.sent();
1403
+ if (!(sessionState_1.state === SessionState.VOD_NEXT_INITIATING)) return [3 /*break*/, 19];
1404
+ _h = sessionState_1;
1413
1405
  return [4 /*yield*/, this._sessionState.set("state", SessionState.VOD_PLAYING)];
1414
1406
  case 18:
1415
1407
  _h.state = _m.sent();
1416
1408
  _m.label = 19;
1417
1409
  case 19:
1418
- debug("[".concat(this._sessionId, "]: VIDEO ").concat(timeSinceLastRequest_1, " (").concat(this.averageSegmentDuration, ") bandwidth=").concat(bw, " vodMediaSeq=(").concat(sessionState_2.vodMediaSeqVideo, "_").concat(sessionState_2.vodMediaSeqAudio, ")"));
1410
+ debug("[".concat(this._sessionId, "]: VIDEO ").concat(timeSinceLastRequest_1, " (").concat(this.averageSegmentDuration, ") bandwidth=").concat(bw, " vodMediaSeq=(").concat(sessionState_1.vodMediaSeqVideo, "_").concat(sessionState_1.vodMediaSeqAudio, ")"));
1419
1411
  try {
1420
- m3u8 = currentVod.getLiveMediaSequences(sessionState_2.mediaSeq, bw, sessionState_2.vodMediaSeqVideo, sessionState_2.discSeq);
1412
+ m3u8 = currentVod.getLiveMediaSequences(sessionState_1.mediaSeq, bw, sessionState_1.vodMediaSeqVideo, sessionState_1.discSeq);
1421
1413
  }
1422
1414
  catch (exc) {
1423
- if (sessionState_2.lastM3u8[bw]) {
1424
- m3u8 = sessionState_2.lastM3u8[bw];
1415
+ if (sessionState_1.lastM3u8[bw]) {
1416
+ m3u8 = sessionState_1.lastM3u8[bw];
1425
1417
  }
1426
1418
  else {
1427
1419
  logerror(this._sessionId, exc);
1428
1420
  throw new Error('Failed to generate media manifest');
1429
1421
  }
1430
1422
  }
1431
- lastM3u8_1 = sessionState_2.lastM3u8;
1423
+ lastM3u8_1 = sessionState_1.lastM3u8;
1432
1424
  lastM3u8_1[bw] = m3u8;
1433
- _j = sessionState_2;
1425
+ _j = sessionState_1;
1434
1426
  return [4 /*yield*/, this._sessionState.set("lastM3u8", lastM3u8_1)];
1435
1427
  case 20:
1436
1428
  _j.lastM3u8 = _m.sent();
1437
- _k = sessionState_2;
1429
+ _k = sessionState_1;
1438
1430
  return [4 /*yield*/, this._sessionState.set("lastServedM3u8", m3u8)];
1439
1431
  case 21:
1440
1432
  _k.lastServedM3u8 = _m.sent();
1441
- _l = sessionState_2;
1433
+ _l = sessionState_1;
1442
1434
  return [4 /*yield*/, this._sessionState.set("tsLastRequestVideo", Date.now())];
1443
1435
  case 22:
1444
1436
  _l.tsLastRequestVideo = _m.sent();
@@ -1764,7 +1756,7 @@ var Session = /** @class */ (function () {
1764
1756
  };
1765
1757
  Session.prototype._tickAsync = function () {
1766
1758
  return __awaiter(this, void 0, void 0, function () {
1767
- var newVod, sessionState, isLeader, currentVod, vodResponse, _a, nextVodPromise, nextVodStart, _b, loadPromise, hlsOpts, _c, mediaManifestLoader, audioManifestLoader, loadStart, updatedSessionState, _d, _e, _f, _g, err_7, _h, length_1, endMseqValue, endMseqValueAudio, endMseqValueSubtitle, lastDiscontinuity, lastDiscontinuityAudio, lastDiscontinuitySubtitle, _j, vodPromise, gracePeriod, nextVodStart, _k, loadPromise, hlsOpts, _l, mediaManifestLoader, audioManifestLoader, loadStart, _m, _o, updatedSessionState, _p, _q, diffMs, err_8, startTS, _r, mSeq, currentVod_2, dSeq, mSeqOffset, reloadBehind, segments, playheadState, nextMseq, _s, _t, err_9;
1759
+ var newVod, sessionState, isLeader, currentVod, vodResponse, _a, nextVodPromise, nextVodStart, _b, loadPromise, hlsOpts, _c, mediaManifestLoader, audioManifestLoader, loadStart, updatedSessionState, _d, _e, _f, _g, err_7, _h, length_1, endMseqValue, endMseqValueAudio, endMseqValueSubtitle, lastDiscontinuity, lastDiscontinuityAudio, lastDiscontinuitySubtitle, _j, vodPromise, gracePeriod, nextVodStart, _k, loadPromise, hlsOpts, _l, mediaManifestLoader, audioManifestLoader, loadStart, _m, _o, updatedSessionState, _p, _q, diffMs, err_8, startTS, _r, mSeq, currentVod_1, dSeq, mSeqOffset, reloadBehind, segments, playheadState, nextMseq, _s, _t, err_9;
1768
1760
  var _this = this;
1769
1761
  return __generator(this, function (_u) {
1770
1762
  switch (_u.label) {
@@ -1870,6 +1862,7 @@ var Session = /** @class */ (function () {
1870
1862
  debug("[".concat(this._sessionId, "]: ").concat(currentVod.getDeltaTimes()));
1871
1863
  debug("[".concat(this._sessionId, "]: playhead positions [V]=").concat(currentVod.getPlayheadPositions("video")));
1872
1864
  debug("[".concat(this._sessionId, "]: playhead positions [A]=").concat(currentVod.getPlayheadPositions("audio")));
1865
+ debug("[".concat(this._sessionId, "]: playhead positions [S]=").concat(currentVod.getPlayheadPositions("subtitle")));
1873
1866
  return [4 /*yield*/, this._sessionState.setValues({
1874
1867
  "mediaSeq": 0,
1875
1868
  "mediaSeqAudio": 0,
@@ -2110,6 +2103,7 @@ var Session = /** @class */ (function () {
2110
2103
  debug("[".concat(this._sessionId, "]: next VOD loaded (").concat(newVod.getDeltaTimes(), ")"));
2111
2104
  debug("[".concat(this._sessionId, "]: playhead positions [V]=").concat(newVod.getPlayheadPositions("video")));
2112
2105
  debug("[".concat(this._sessionId, "]: playhead positions [A]=").concat(newVod.getPlayheadPositions("audio")));
2106
+ debug("[".concat(this._sessionId, "]: playhead positions [S]=").concat(newVod.getPlayheadPositions("subtitle")));
2113
2107
  currentVod = newVod;
2114
2108
  debug("[".concat(this._sessionId, "]: msequences=").concat(currentVod.getLiveMediaSequencesCount(), "; audio msequences=").concat(currentVod.getLiveMediaSequencesCount("audio"), "; subtitle msequences=").concat(currentVod.getLiveMediaSequencesCount("subtitle")));
2115
2109
  _m = sessionState;
@@ -2216,8 +2210,8 @@ var Session = /** @class */ (function () {
2216
2210
  mSeq = this.switchDataForSession.mediaSeq;
2217
2211
  return [4 /*yield*/, this._sessionState.getCurrentVod()];
2218
2212
  case 63:
2219
- currentVod_2 = _u.sent();
2220
- if (currentVod_2.sequenceAlwaysContainNewSegments) {
2213
+ currentVod_1 = _u.sent();
2214
+ if (currentVod_1.sequenceAlwaysContainNewSegments) {
2221
2215
  // (!) will need to compensate if using this setting on HLSVod Object.
2222
2216
  Object.keys(this.switchDataForSession.transitionSegments).forEach(function (bw) {
2223
2217
  var shiftedSeg = _this.switchDataForSession.transitionSegments[bw].shift();
@@ -2251,19 +2245,19 @@ var Session = /** @class */ (function () {
2251
2245
  case 67:
2252
2246
  playheadState = _u.sent();
2253
2247
  nextMseq = playheadState.vodMediaSeqVideo + 1;
2254
- if (nextMseq > currentVod_2.getLiveMediaSequencesCount() - 1) {
2255
- nextMseq = currentVod_2.getLiveMediaSequencesCount() - 1;
2248
+ if (nextMseq > currentVod_1.getLiveMediaSequencesCount() - 1) {
2249
+ nextMseq = currentVod_1.getLiveMediaSequencesCount() - 1;
2256
2250
  }
2257
2251
  // ---------------------------------------------------.
2258
2252
  // TODO: Support reloading with audioSegments and SubtitleSegments as well |
2259
2253
  // ---------------------------------------------------'
2260
- return [4 /*yield*/, currentVod_2.reload(nextMseq, segments, null, reloadBehind)];
2254
+ return [4 /*yield*/, currentVod_1.reload(nextMseq, segments, null, reloadBehind)];
2261
2255
  case 68:
2262
2256
  // ---------------------------------------------------.
2263
2257
  // TODO: Support reloading with audioSegments and SubtitleSegments as well |
2264
2258
  // ---------------------------------------------------'
2265
2259
  _u.sent();
2266
- return [4 /*yield*/, this._sessionState.setCurrentVod(currentVod_2, { ttl: currentVod_2.getDuration() * 1000 })];
2260
+ return [4 /*yield*/, this._sessionState.setCurrentVod(currentVod_1, { ttl: currentVod_1.getDuration() * 1000 })];
2267
2261
  case 69:
2268
2262
  _u.sent();
2269
2263
  return [4 /*yield*/, this._sessionState.set("vodReloaded", 1)];
@@ -2293,9 +2287,9 @@ var Session = /** @class */ (function () {
2293
2287
  _s.currentPlayheadRef = _u.sent();
2294
2288
  // 4) Log to debug and cloudwatch
2295
2289
  debug("[".concat(this._sessionId, "]: LEADER: Set new Reloaded VOD and vodMediaSeq counts in store."));
2296
- debug("[".concat(this._sessionId, "]: next VOD Reloaded (").concat(currentVod_2.getDeltaTimes(), ")"));
2297
- debug("[".concat(this._sessionId, "]: ").concat(currentVod_2.getPlayheadPositions()));
2298
- debug("[".concat(this._sessionId, "]: msequences=").concat(currentVod_2.getLiveMediaSequencesCount()));
2290
+ debug("[".concat(this._sessionId, "]: next VOD Reloaded (").concat(currentVod_1.getDeltaTimes(), ")"));
2291
+ debug("[".concat(this._sessionId, "]: ").concat(currentVod_1.getPlayheadPositions()));
2292
+ debug("[".concat(this._sessionId, "]: msequences=").concat(currentVod_1.getLiveMediaSequencesCount()));
2299
2293
  cloudWatchLog(!this.cloudWatchLogging, "engine-session", { event: "switchback", channel: this._sessionId, reqTimeMs: Date.now() - startTS });
2300
2294
  return [2 /*return*/];
2301
2295
  case 78:
@@ -2727,6 +2721,50 @@ var Session = /** @class */ (function () {
2727
2721
  }
2728
2722
  return false;
2729
2723
  };
2724
+ Session.prototype._determineExtraMediaIncrement = function (_extraType, _currentPosVideo, _extraSeqFinalIndex, _vodMediaSeqExtra, _getExtraPlayheadPositionAsyncFn) {
2725
+ return __awaiter(this, void 0, void 0, function () {
2726
+ var extraMediaIncrement, positionV, positionX, posDiff, threshold, currentPosExtraMedia, difference;
2727
+ return __generator(this, function (_a) {
2728
+ switch (_a.label) {
2729
+ case 0:
2730
+ debug("[".concat(this._sessionId, "]: About to determine ").concat(_extraType, " increment. Video increment has already been executed."));
2731
+ extraMediaIncrement = 0;
2732
+ positionV = _currentPosVideo ? _currentPosVideo / 1000 : 0;
2733
+ threshold = 0.500;
2734
+ _a.label = 1;
2735
+ case 1:
2736
+ if (!(extraMediaIncrement < _extraSeqFinalIndex)) return [3 /*break*/, 3];
2737
+ return [4 /*yield*/, _getExtraPlayheadPositionAsyncFn(_vodMediaSeqExtra + extraMediaIncrement)];
2738
+ case 2:
2739
+ currentPosExtraMedia = (_a.sent()) * 1000;
2740
+ positionX = currentPosExtraMedia ? currentPosExtraMedia / 1000 : 0;
2741
+ posDiff = (positionV - positionX).toFixed(3);
2742
+ debug("[".concat(this._sessionId, "]: positionV=").concat(positionV, ";position").concat(_extraType === "audio" ? "A" : "S", "=").concat(positionX, ";posDiff=").concat(posDiff));
2743
+ if (isNaN(posDiff)) {
2744
+ return [3 /*break*/, 3];
2745
+ }
2746
+ if (positionX >= positionV) {
2747
+ return [3 /*break*/, 3];
2748
+ }
2749
+ difference = Math.abs(posDiff);
2750
+ if (difference > threshold && difference > Number.EPSILON) {
2751
+ // Video position ahead of audio|sub position, further increment needed...
2752
+ extraMediaIncrement++;
2753
+ }
2754
+ else {
2755
+ debug("[".concat(this._sessionId, "]: Difference(").concat(difference, ") is acceptable; IncrementValue=").concat(extraMediaIncrement));
2756
+ return [3 /*break*/, 3];
2757
+ }
2758
+ return [3 /*break*/, 1];
2759
+ case 3: return [2 /*return*/, {
2760
+ increment: extraMediaIncrement,
2761
+ position: positionX,
2762
+ diff: posDiff
2763
+ }];
2764
+ }
2765
+ });
2766
+ });
2767
+ };
2730
2768
  return Session;
2731
2769
  }());
2732
2770
  module.exports = Session;
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eyevinn-channel-engine",
3
- "version": "4.3.7",
3
+ "version": "4.3.9",
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": "^4.1.0",
33
+ "@eyevinn/hls-vodtolive": "^4.1.1",
34
34
  "@eyevinn/m3u8": "^0.5.3",
35
35
  "abort-controller": "^3.0.0",
36
36
  "debug": "^3.2.7",
package/engine/session.js CHANGED
@@ -834,51 +834,51 @@ class Session {
834
834
  }
835
835
  } else {
836
836
  sessionState.vodMediaSeqVideo = await this._sessionState.increment("vodMediaSeqVideo", 1);
837
- let audioIncrement;
837
+ let playheadPosVideoMs;
838
+ let playheadAudio;
839
+ let playheadSubtitle;
840
+ if (this.use_demuxed_audio || this.use_vtt_subtitles) {
841
+ playheadPosVideoMs = (await this._getCurrentPlayheadPosition()) * 1000;
842
+ }
843
+
838
844
  if (this.use_demuxed_audio) {
839
- let positionV = 0;
840
- let positionA = 0;
841
- const position = (await this._getCurrentPlayheadPosition()) * 1000;
842
- positionV = position ? position / 1000 : 0;
843
- let currentVod = await this._sessionState.getCurrentVod();
844
- const sessionState = await this._sessionState.getValues(["vodMediaSeqAudio"]);
845
- let posDiff;
846
- let incrementValue = 1;
847
- let index = 0;
848
845
  const audioSeqLastIdx = currentVod.getLiveMediaSequencesCount("audio") - 1;
849
- const thresh = 0.5;
850
- const maxAcceptableDiff = 0.001;
851
- debug(`[${this._sessionId}]: About to determine audio increment`);
852
- do {
853
- const audioPosition = (await this._getAudioPlayheadPosition(sessionState.vodMediaSeqAudio + index)) * 1000;
854
- positionA = audioPosition ? audioPosition / 1000 : 0;
855
- posDiff = (positionV - positionA).toFixed(3);
856
- debug(`[${this._sessionId}]: positionV=${positionV};positionA=${positionA};posDiff=${posDiff}`);
857
- if (posDiff <= maxAcceptableDiff) {
858
- break;
859
- }
860
- if (posDiff > thresh) {
861
- index++;
862
- incrementValue++;
863
- } else if (posDiff > maxAcceptableDiff) {
864
- index = incrementValue;
865
- debug(`[${this._sessionId}]: Audio Stepping index set to = ${index}`);
866
- break;
867
- }
868
- if (sessionState.vodMediaSeqAudio + index > audioSeqLastIdx) {
869
- break;
870
- }
871
- } while (!(-thresh < posDiff && posDiff < thresh) && !isNaN(posDiff));
872
- audioIncrement = index;
873
- debug(`[${this._sessionId}]: Current VOD Playhead Positions are to be: [${positionV.toFixed(3)}][${positionA.toFixed(3)}] (${posDiff})`);
846
+ const sessionStateObj = await this._sessionState.getValues(["vodMediaSeqAudio"]);
847
+ playheadAudio = await this._determineExtraMediaIncrement(
848
+ "audio",
849
+ playheadPosVideoMs,
850
+ audioSeqLastIdx,
851
+ sessionStateObj.vodMediaSeqAudio,
852
+ this._getAudioPlayheadPosition.bind(this)
853
+ );
854
+ // Perform the Increment
855
+ debug(`[${this._sessionId}]: Will increment audio with ${playheadAudio.increment}`);
856
+ sessionState.vodMediaSeqAudio = await this._sessionState.increment("vodMediaSeqAudio", playheadAudio.increment);
874
857
  }
875
- debug(`[${this._sessionId}]: Will increment audio with ${audioIncrement}`);
876
- sessionState.vodMediaSeqAudio = await this._sessionState.increment("vodMediaSeqAudio", audioIncrement);
877
-
878
858
  if (this.use_vtt_subtitles) {
879
- debug(`[${this._sessionId}]: Will increment subtitle with 1`);
880
- sessionState.vodMediaSeqSubtitle = await this._sessionState.increment("vodMediaSeqSubtitle", 1);
859
+ const playheadPosVideo = playheadPosVideo || (await this._getCurrentPlayheadPosition()) * 1000;
860
+ const subtitleSeqLastIdx = currentVod.getLiveMediaSequencesCount("subtitle") - 1;
861
+ const sessionStateObj = await this._sessionState.getValues(["vodMediaSeqSubtitle"]);
862
+ playheadSubtitle = await this._determineExtraMediaIncrement(
863
+ "subtitle",
864
+ playheadPosVideoMs,
865
+ subtitleSeqLastIdx,
866
+ sessionStateObj.vodMediaSeqSubtitle,
867
+ this._getSubtitlePlayheadPosition.bind(this)
868
+ );
869
+ // Perform the Increment
870
+ debug(`[${this._sessionId}]: Will increment subtitle with ${playheadSubtitle.increment}`);
871
+ sessionState.vodMediaSeqSubtitle = await this._sessionState.increment("vodMediaSeqSubtitle", playheadSubtitle.increment);
881
872
  }
873
+ debug(`[${this._sessionId}]: Current VOD Playhead Positions are to be V[${(playheadPosVideoMs/1000).toFixed(3)}]${
874
+ playheadAudio ? `A[${(playheadAudio.position).toFixed(3)}]` : ""
875
+ }${
876
+ playheadSubtitle ? `S[${(playheadSubtitle.position).toFixed(3)})]` : ""
877
+ }${
878
+ playheadAudio ? ` (${playheadAudio.diff})` : ""
879
+ }${
880
+ playheadSubtitle ? ` (${playheadSubtitle.diff})` : ""
881
+ }`);
882
882
  }
883
883
 
884
884
  let newSessionState = {};
@@ -923,10 +923,19 @@ class Session {
923
923
  const mediaSequenceValueAudio = currentVod.mediaSequenceValuesAudio[playheadState.vodMediaSeqAudio];
924
924
  audioInfo = ` mseq[A]={${playheadState.mediaSeqAudio + mediaSequenceValueAudio}}`
925
925
  }
926
- debug(`[${this._sessionId}]: Session can now serve mseq[V]={${playheadState.mediaSeq + mediaSequenceValue}}` + audioInfo);
926
+ let subsInfo = "";
927
+ if (this.use_vtt_subtitles) {
928
+ const mediaSequenceValueSubtitle = currentVod.mediaSequenceValuesSubtitle[playheadState.vodMediaSeqSubtitle];
929
+ subsInfo = ` mseq[S]={${playheadState.mediaSeqSubtitle + mediaSequenceValueSubtitle}}`
930
+ }
931
+ debug(`[${this._sessionId}]: Session can now serve mseq[V]={${playheadState.mediaSeq + mediaSequenceValue}}` + audioInfo + subsInfo);
927
932
  }
928
933
 
929
- debug(`[${this._sessionId}]: INCREMENT (mseq=${playheadState.mediaSeq + playheadState.vodMediaSeqVideo}) vodMediaSeq=(${playheadState.vodMediaSeqVideo}_${playheadState.vodMediaSeqAudio} of ${currentVod.getLiveMediaSequencesCount()}_${currentVod.getLiveMediaSequencesCount("audio")})`);
934
+ debug(`[${this._sessionId}]: INCREMENT (mseq=${playheadState.mediaSeq + playheadState.vodMediaSeqVideo}) vodMediaSeq=(${playheadState.vodMediaSeqVideo}_${playheadState.vodMediaSeqAudio}${
935
+ this.use_vtt_subtitles ? `_${playheadState.vodMediaSeqSubtitle}` : ""
936
+ } of ${currentVod.getLiveMediaSequencesCount()}_${currentVod.getLiveMediaSequencesCount("audio")}${
937
+ this.use_vtt_subtitles ? `_${currentVod.getLiveMediaSequencesCount("subtitle")})` : ")"
938
+ }`);
930
939
 
931
940
  // As a FOLLOWER, we might need to read up from shared store...
932
941
  if (playheadState.vodMediaSeqVideo < 2 || playheadState.mediaSeq !== this.prevMediaSeqOffset.video) {
@@ -1388,6 +1397,7 @@ class Session {
1388
1397
  debug(`[${this._sessionId}]: ${currentVod.getDeltaTimes()}`);
1389
1398
  debug(`[${this._sessionId}]: playhead positions [V]=${currentVod.getPlayheadPositions("video")}`);
1390
1399
  debug(`[${this._sessionId}]: playhead positions [A]=${currentVod.getPlayheadPositions("audio")}`);
1400
+ debug(`[${this._sessionId}]: playhead positions [S]=${currentVod.getPlayheadPositions("subtitle")}`);
1391
1401
  //debug(newVod);
1392
1402
  const updatedSessionState = await this._sessionState.setValues({
1393
1403
  "mediaSeq": 0,
@@ -1584,6 +1594,7 @@ class Session {
1584
1594
  debug(`[${this._sessionId}]: next VOD loaded (${newVod.getDeltaTimes()})`);
1585
1595
  debug(`[${this._sessionId}]: playhead positions [V]=${newVod.getPlayheadPositions("video")}`);
1586
1596
  debug(`[${this._sessionId}]: playhead positions [A]=${newVod.getPlayheadPositions("audio")}`);
1597
+ debug(`[${this._sessionId}]: playhead positions [S]=${newVod.getPlayheadPositions("subtitle")}`);
1587
1598
  currentVod = newVod;
1588
1599
  debug(`[${this._sessionId}]: msequences=${currentVod.getLiveMediaSequencesCount()}; audio msequences=${currentVod.getLiveMediaSequencesCount("audio")}; subtitle msequences=${currentVod.getLiveMediaSequencesCount("subtitle")}`);
1589
1600
  sessionState.currentVod = await this._sessionState.setCurrentVod(currentVod, { ttl: currentVod.getDuration() * 1000 });
@@ -2089,6 +2100,40 @@ class Session {
2089
2100
  }
2090
2101
  return false;
2091
2102
  }
2103
+
2104
+ async _determineExtraMediaIncrement(_extraType, _currentPosVideo, _extraSeqFinalIndex, _vodMediaSeqExtra, _getExtraPlayheadPositionAsyncFn) {
2105
+ debug(`[${this._sessionId}]: About to determine ${_extraType} increment. Video increment has already been executed.`);
2106
+ let extraMediaIncrement = 0;
2107
+ let positionV = _currentPosVideo ? _currentPosVideo / 1000 : 0;
2108
+ let positionX;
2109
+ let posDiff;
2110
+ const threshold = 0.500;
2111
+ while (extraMediaIncrement < _extraSeqFinalIndex) {
2112
+ const currentPosExtraMedia = (await _getExtraPlayheadPositionAsyncFn(_vodMediaSeqExtra + extraMediaIncrement)) * 1000;
2113
+ positionX = currentPosExtraMedia ? currentPosExtraMedia / 1000 : 0;
2114
+ posDiff = (positionV - positionX).toFixed(3);
2115
+ debug(`[${this._sessionId}]: positionV=${positionV};position${_extraType === "audio" ? "A" : "S"}=${positionX};posDiff=${posDiff}`);
2116
+ if (isNaN(posDiff)) {
2117
+ break;
2118
+ }
2119
+ if (positionX >= positionV) {
2120
+ break;
2121
+ }
2122
+ const difference = Math.abs(posDiff);
2123
+ if (difference > threshold && difference > Number.EPSILON) {
2124
+ // Video position ahead of audio|sub position, further increment needed...
2125
+ extraMediaIncrement++;
2126
+ } else {
2127
+ debug(`[${this._sessionId}]: Difference(${difference}) is acceptable; IncrementValue=${extraMediaIncrement}`);
2128
+ break;
2129
+ }
2130
+ }
2131
+ return {
2132
+ increment: extraMediaIncrement,
2133
+ position: positionX,
2134
+ diff: posDiff
2135
+ };
2136
+ }
2092
2137
  }
2093
2138
 
2094
2139
  module.exports = Session;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eyevinn-channel-engine",
3
- "version": "4.3.7",
3
+ "version": "4.3.9",
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": "^4.1.0",
33
+ "@eyevinn/hls-vodtolive": "^4.1.1",
34
34
  "@eyevinn/m3u8": "^0.5.3",
35
35
  "abort-controller": "^3.0.0",
36
36
  "debug": "^3.2.7",
@@ -1,20 +1,116 @@
1
- const Session = require('../../engine/session.js');
1
+ const Session = require("../../engine/session.js");
2
2
 
3
- const { SessionStateStore } = require('../../engine/session_state.js');
4
- const { PlayheadStateStore } = require('../../engine/playhead_state.js');
3
+ const { SessionStateStore } = require("../../engine/session_state.js");
4
+ const { PlayheadStateStore } = require("../../engine/playhead_state.js");
5
5
 
6
6
  describe("Session", () => {
7
7
  let sessionLiveStore = undefined;
8
8
  beforeEach(() => {
9
9
  sessionLiveStore = {
10
10
  sessionStateStore: new SessionStateStore(),
11
- playheadStateStore: new PlayheadStateStore()
12
- };
11
+ playheadStateStore: new PlayheadStateStore(),
12
+ };
13
13
  });
14
14
 
15
15
  it("creates a unique session ID", () => {
16
- const id1 = new Session('dummy', null, sessionLiveStore).sessionId;
17
- const id2 = new Session('dummy', null, sessionLiveStore).sessionId;
16
+ const id1 = new Session("dummy", null, sessionLiveStore).sessionId;
17
+ const id2 = new Session("dummy", null, sessionLiveStore).sessionId;
18
18
  expect(id1).not.toEqual(id2);
19
19
  });
20
- });
20
+
21
+ it("for demuxed, returns the appropriate audio increment value when desync is within acceptable limit, case I", async () => {
22
+ const session = new Session("dummy", null, sessionLiveStore);
23
+ const mockFinalAudioIdx = 50; // current Vod has 50 media sequences to serve.
24
+ const mockCurrentVideoPosition = 200.0 * 1000; // Video is 200s deep into its content.
25
+ const mockMseqAudio = 25; // current mseq for audio on vod, 25 out of 50.
26
+ const mock_getAudioPlayheadPosition = async (pos_n_current) => {
27
+ const mockPositions = [196.0, 199.84, 203.68, 207.52];
28
+ return mockPositions[pos_n_current - mockMseqAudio];
29
+ };
30
+ const output = await session._determineExtraMediaIncrement(
31
+ "audio",
32
+ mockCurrentVideoPosition,
33
+ mockFinalAudioIdx,
34
+ mockMseqAudio,
35
+ mock_getAudioPlayheadPosition,
36
+ 24
37
+ );
38
+ expect(output.increment).toBe(1);
39
+ });
40
+
41
+ it("for demuxed, returns the appropriate audio increment value when desync is within acceptable limit, case II", async () => {
42
+ const session = new Session("dummy", null, sessionLiveStore);
43
+ const mockFinalAudioIdx = 50; // current Vod has 50 media sequences to serve.
44
+ const mockCurrentVideoPosition = 200.0 * 1000; // Video is 200s deep into its content.
45
+ const mockMseqAudio = 25; // current mseq for audio on vod, 25 out of 50.
46
+ const mock_getAudioPlayheadPosition = async (pos_n_current) => {
47
+ const mockPositions = [192.16, 196.0, 199.84, 203.68, 207.52];
48
+ return mockPositions[pos_n_current - mockMseqAudio];
49
+ };
50
+ const output = await session._determineExtraMediaIncrement(
51
+ "audio",
52
+ mockCurrentVideoPosition,
53
+ mockFinalAudioIdx,
54
+ mockMseqAudio,
55
+ mock_getAudioPlayheadPosition,
56
+ 24
57
+ );
58
+ expect(output.increment).toBe(2);
59
+ });
60
+
61
+ it("for demuxed, returns the appropriate audio increment value when they are in sync but there is a floating point error", async () => {
62
+ const session = new Session("dummy", null, sessionLiveStore);
63
+ const mockFinalAudioIdx = 50;
64
+ const mockCurrentVideoPosition = 441.7599999999981697 * 1000;
65
+ const mockMseqAudio = 25;
66
+ const mock_getAudioPlayheadPosition = async (pos_n_current) => {
67
+ const mockPositions = [437.919999999999, 441.75999999999897];
68
+ return mockPositions[pos_n_current - mockMseqAudio];
69
+ };
70
+ const output = await session._determineExtraMediaIncrement(
71
+ "audio",
72
+ mockCurrentVideoPosition,
73
+ mockFinalAudioIdx,
74
+ mockMseqAudio,
75
+ mock_getAudioPlayheadPosition,
76
+ 24
77
+ );
78
+ expect(output.increment).toBe(1);
79
+ });
80
+ it("for demuxed, returns the appropriate audio increment value, normal case I", async () => {
81
+ const session = new Session("dummy", null, sessionLiveStore);
82
+ const mockFinalAudioIdx = 50;
83
+ const mockCurrentVideoPosition = 3.840 * 8 * 1000;
84
+ const mockMseqAudio = 5;
85
+ const mock_getAudioPlayheadPosition = async (pos_n_current) => {
86
+ const mockPositions = [0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52];
87
+ return mockPositions[pos_n_current];
88
+ };
89
+ const output = await session._determineExtraMediaIncrement(
90
+ "audio",
91
+ mockCurrentVideoPosition,
92
+ mockFinalAudioIdx,
93
+ mockMseqAudio,
94
+ mock_getAudioPlayheadPosition
95
+ );
96
+ expect(output.increment).toBe(3);
97
+ });
98
+ it("for demuxed, returns the appropriate audio increment value, normal case II", async () => {
99
+ const session = new Session("dummy", null, sessionLiveStore);
100
+ const mockFinalAudioIdx = 50;
101
+ const mockCurrentVideoPosition = 14 * 1000;
102
+ const mockMseqAudio = 0;
103
+ const mock_getAudioPlayheadPosition = async (pos_n_current) => {
104
+ const mockPositions = [0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52];
105
+ return mockPositions[pos_n_current];
106
+ };
107
+ const output = await session._determineExtraMediaIncrement(
108
+ "subtitle",
109
+ mockCurrentVideoPosition,
110
+ mockFinalAudioIdx,
111
+ mockMseqAudio,
112
+ mock_getAudioPlayheadPosition
113
+ );
114
+ expect(output.increment).toBe(4);
115
+ });
116
+ });