eyevinn-channel-engine 5.0.3 → 5.0.5

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.
@@ -34,6 +34,7 @@ export interface ChannelEngineOpts {
34
34
  keepAliveTimeout?: number;
35
35
  sessionEventStream?: boolean;
36
36
  sessionHealthKey?: string;
37
+ rollingPDT?: boolean;
37
38
  }
38
39
  export interface VodRequest {
39
40
  sessionId: string;
@@ -462,7 +462,8 @@ var ChannelEngine = /** @class */ (function () {
462
462
  slateRepetitions: channel.slate && channel.slate.repetitions ? channel.slate.repetitions : this.slateRepetitions,
463
463
  slateDuration: channel.slate && channel.slate.duration ? channel.slate.duration : this.slateDuration,
464
464
  cloudWatchMetrics: this.logCloudWatchMetrics,
465
- sessionEventStream: options.sessionEventStream
465
+ sessionEventStream: options.sessionEventStream,
466
+ rollingPDT: options.rollingPDT
466
467
  }, this.sessionStore);
467
468
  sessionsLive[channel.id] = new SessionLive({
468
469
  sessionId: channel.id,
@@ -57,6 +57,7 @@ declare class Session {
57
57
  partialStoreHLSVod: any;
58
58
  currentPlayheadRef: any;
59
59
  disableLegacyMasterManifestFormat: any;
60
+ rollingPDT: any;
60
61
  _category: any;
61
62
  startWithId: any;
62
63
  _sessionProfile: any;
@@ -117,10 +118,10 @@ declare class Session {
117
118
  _insertSlate(currentVod: any): Promise<any>;
118
119
  _tickAsync(): Promise<void>;
119
120
  _getNextVod(): Promise<any>;
120
- _loadSlate(afterVod: any, reps: any): Promise<any>;
121
+ _loadSlate(afterVod: any, reps: any, unixTs: any): Promise<any>;
121
122
  _truncateVod(vodResponse: any): Promise<any>;
122
- _truncateSlate(afterVod: any, requestedDuration: any, vodUri: any): Promise<any>;
123
- _fillGap(afterVod: any, desiredDuration: any): Promise<any>;
123
+ _truncateSlate(afterVod: any, requestedDuration: any, vodUri: any, unixTs: any): Promise<any>;
124
+ _fillGap(afterVod: any, desiredDuration: any, unixTs: any): Promise<any>;
124
125
  _getNextVodById(id: any): Promise<any>;
125
126
  _getFirstDuration(manifest: any): Promise<any>;
126
127
  _getCurrentDeltaTime(): Promise<any>;
@@ -137,6 +137,7 @@ var Session = /** @class */ (function () {
137
137
  this.partialStoreHLSVod = null;
138
138
  this.currentPlayheadRef = null;
139
139
  this.disableLegacyMasterManifestFormat = null;
140
+ this.rollingPDT = null;
140
141
  if (config) {
141
142
  if (config.alwaysNewSegments) {
142
143
  this.alwaysNewSegments = config.alwaysNewSegments;
@@ -147,6 +148,9 @@ var Session = /** @class */ (function () {
147
148
  if (config.partialStoreHLSVod) {
148
149
  this.partialStoreHLSVod = config.partialStoreHLSVod;
149
150
  }
151
+ if (config.rollingPDT) {
152
+ this.rollingPDT = config.rollingPDT;
153
+ }
150
154
  if (config.alwaysMapBandwidthByNearest) {
151
155
  this.alwaysMapBandwidthByNearest = config.alwaysMapBandwidthByNearest;
152
156
  }
@@ -1749,7 +1753,8 @@ var Session = /** @class */ (function () {
1749
1753
  shouldContainSubtitles: this.use_vtt_subtitles,
1750
1754
  expectedSubtitleTracks: this._subtitleTracks,
1751
1755
  alwaysMapBandwidthByNearest: this.alwaysMapBandwidthByNearest,
1752
- skipSerializeMediaSequences: this.partialStoreHLSVod
1756
+ skipSerializeMediaSequences: this.partialStoreHLSVod,
1757
+ calculatePDT: this.rollingPDT
1753
1758
  };
1754
1759
  newVod = new HLSVod(vodResponse.uri, [], vodResponse.unixTs, vodResponse.offset * 1000, m3u8Header(this._instanceId), hlsOpts);
1755
1760
  if (vodResponse.timedMetadata) {
@@ -1780,7 +1785,7 @@ var Session = /** @class */ (function () {
1780
1785
  case 15:
1781
1786
  if (vodResponse.type === 'gap') {
1782
1787
  loadPromise = new Promise(function (resolve, reject) {
1783
- _this._fillGap(null, vodResponse.desiredDuration)
1788
+ _this._fillGap(null, vodResponse.desiredDuration, vodResponse.unixTs)
1784
1789
  .then(function (gapVod) {
1785
1790
  currentVod = gapVod;
1786
1791
  resolve(gapVod);
@@ -1981,7 +1986,8 @@ var Session = /** @class */ (function () {
1981
1986
  shouldContainSubtitles: this.use_vtt_subtitles,
1982
1987
  expectedSubtitleTracks: this._subtitleTracks,
1983
1988
  alwaysMapBandwidthByNearest: this.alwaysMapBandwidthByNearest,
1984
- skipSerializeMediaSequences: this.partialStoreHLSVod
1989
+ skipSerializeMediaSequences: this.partialStoreHLSVod,
1990
+ calculatePDT: this.rollingPDT
1985
1991
  };
1986
1992
  newVod = new HLSVod(vodResponse.uri, null, vodResponse.unixTs, vodResponse.offset * 1000, m3u8Header(this._instanceId), hlsOpts);
1987
1993
  if (vodResponse.timedMetadata) {
@@ -2029,7 +2035,7 @@ var Session = /** @class */ (function () {
2029
2035
  return [3 /*break*/, 51];
2030
2036
  case 50:
2031
2037
  loadPromise = new Promise(function (resolve, reject) {
2032
- _this._fillGap(currentVod, vodResponse.desiredDuration)
2038
+ _this._fillGap(currentVod, vodResponse.desiredDuration, vodResponse.unixTs)
2033
2039
  .then(function (gapVod) {
2034
2040
  newVod = gapVod;
2035
2041
  resolve(newVod);
@@ -2376,7 +2382,7 @@ var Session = /** @class */ (function () {
2376
2382
  .catch(reject);
2377
2383
  });
2378
2384
  };
2379
- Session.prototype._loadSlate = function (afterVod, reps) {
2385
+ Session.prototype._loadSlate = function (afterVod, reps, unixTs) {
2380
2386
  var _this = this;
2381
2387
  return new Promise(function (resolve, reject) {
2382
2388
  try {
@@ -2392,9 +2398,10 @@ var Session = /** @class */ (function () {
2392
2398
  shouldContainSubtitles: _this.use_vtt_subtitles,
2393
2399
  expectedSubtitleTracks: _this._subtitleTracks,
2394
2400
  alwaysMapBandwidthByNearest: _this.alwaysMapBandwidthByNearest,
2395
- skipSerializeMediaSequences: _this.partialStoreHLSVod
2401
+ skipSerializeMediaSequences: _this.partialStoreHLSVod,
2402
+ calculatePDT: _this.rollingPDT
2396
2403
  };
2397
- var timestamp = Date.now();
2404
+ var timestamp = unixTs ? unixTs : Date.now();
2398
2405
  hlsVod_1 = new HLSVod(_this.slateUri, null, timestamp, null, m3u8Header(_this._instanceId), hlsOpts);
2399
2406
  hlsVod_1.addMetadata('id', "slate-".concat(timestamp));
2400
2407
  hlsVod_1.addMetadata('start-date', new Date(timestamp).toISOString());
@@ -2496,7 +2503,7 @@ var Session = /** @class */ (function () {
2496
2503
  }
2497
2504
  });
2498
2505
  };
2499
- Session.prototype._truncateSlate = function (afterVod, requestedDuration, vodUri) {
2506
+ Session.prototype._truncateSlate = function (afterVod, requestedDuration, vodUri, unixTs) {
2500
2507
  var _this = this;
2501
2508
  return new Promise(function (resolve, reject) {
2502
2509
  var nexVodUri = null;
@@ -2519,9 +2526,10 @@ var Session = /** @class */ (function () {
2519
2526
  shouldContainSubtitles: _this.use_vtt_subtitles,
2520
2527
  expectedSubtitleTracks: _this._subtitleTracks,
2521
2528
  alwaysMapBandwidthByNearest: _this.alwaysMapBandwidthByNearest,
2522
- skipSerializeMediaSequences: _this.partialStoreHLSVod
2529
+ skipSerializeMediaSequences: _this.partialStoreHLSVod,
2530
+ calculatePDT: _this.rollingPDT
2523
2531
  };
2524
- var timestamp = Date.now();
2532
+ var timestamp = unixTs ? unixTs : Date.now();
2525
2533
  hlsVod_2 = new HLSVod(nexVodUri, null, timestamp, null, m3u8Header(_this._instanceId), hlsOpts);
2526
2534
  hlsVod_2.addMetadata('id', "slate-".concat(timestamp));
2527
2535
  hlsVod_2.addMetadata('start-date', new Date(timestamp).toISOString());
@@ -2578,7 +2586,7 @@ var Session = /** @class */ (function () {
2578
2586
  }
2579
2587
  });
2580
2588
  };
2581
- Session.prototype._fillGap = function (afterVod, desiredDuration) {
2589
+ Session.prototype._fillGap = function (afterVod, desiredDuration, unixTs) {
2582
2590
  var _this = this;
2583
2591
  return new Promise(function (resolve, reject) {
2584
2592
  var loadSlatePromise;
@@ -2586,12 +2594,12 @@ var Session = /** @class */ (function () {
2586
2594
  if (desiredDuration > _this.slateDuration) {
2587
2595
  var reps = Math.floor(desiredDuration / _this.slateDuration);
2588
2596
  debug("[".concat(_this._sessionId, "]: Trying to fill a gap of ").concat(desiredDuration, " milliseconds (").concat(reps, " repetitions)"));
2589
- loadSlatePromise = _this._loadSlate(afterVod, reps);
2597
+ loadSlatePromise = _this._loadSlate(afterVod, reps, unixTs);
2590
2598
  durationMs = (reps || _this.slateRepetitions) * _this.slateDuration;
2591
2599
  }
2592
2600
  else {
2593
2601
  debug("[".concat(_this._sessionId, "]: Trying to fill a gap of ").concat(desiredDuration, " milliseconds by truncating filler slate (").concat(_this.slateDuration, ")"));
2594
- loadSlatePromise = _this._truncateSlate(afterVod, desiredDuration / 1000);
2602
+ loadSlatePromise = _this._truncateSlate(afterVod, desiredDuration / 1000, null, unixTs);
2595
2603
  durationMs = desiredDuration;
2596
2604
  }
2597
2605
  loadSlatePromise.then(function (hlsVod) {
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eyevinn-channel-engine",
3
- "version": "5.0.3",
3
+ "version": "5.0.5",
4
4
  "description": "OTT TV Channel Engine",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -31,9 +31,9 @@
31
31
  "dependencies": {
32
32
  "@eyevinn/hls-repeat": "^0.2.1",
33
33
  "@eyevinn/hls-truncate": "^0.3.3",
34
- "@eyevinn/hls-vodtolive": "^4.1.7",
34
+ "@eyevinn/hls-vodtolive": "^4.1.9",
35
35
  "@eyevinn/m3u8": "^0.5.6",
36
- "@fastify/static": "^5.0.0",
36
+ "@fastify/static": "^8.1.1",
37
37
  "abort-controller": "^3.0.0",
38
38
  "debug": "^3.2.7",
39
39
  "fastify": "^3.29.0",
package/engine/server.ts CHANGED
@@ -65,6 +65,7 @@ export interface ChannelEngineOpts {
65
65
  keepAliveTimeout?: number;
66
66
  sessionEventStream?: boolean;
67
67
  sessionHealthKey?: string;
68
+ rollingPDT?: boolean;
68
69
  }
69
70
 
70
71
  interface StreamerOpts {
@@ -499,7 +500,8 @@ export class ChannelEngine {
499
500
  slateRepetitions: channel.slate && channel.slate.repetitions ? channel.slate.repetitions : this.slateRepetitions,
500
501
  slateDuration: channel.slate && channel.slate.duration ? channel.slate.duration : this.slateDuration,
501
502
  cloudWatchMetrics: this.logCloudWatchMetrics,
502
- sessionEventStream: options.sessionEventStream
503
+ sessionEventStream: options.sessionEventStream,
504
+ rollingPDT: options.rollingPDT
503
505
  }, this.sessionStore);
504
506
 
505
507
  sessionsLive[channel.id] = new SessionLive({
package/engine/session.js CHANGED
@@ -87,6 +87,7 @@ class Session {
87
87
  this.partialStoreHLSVod = null;
88
88
  this.currentPlayheadRef = null;
89
89
  this.disableLegacyMasterManifestFormat = null;
90
+ this.rollingPDT = null;
90
91
  if (config) {
91
92
  if (config.alwaysNewSegments) {
92
93
  this.alwaysNewSegments = config.alwaysNewSegments;
@@ -97,7 +98,9 @@ class Session {
97
98
  if (config.partialStoreHLSVod) {
98
99
  this.partialStoreHLSVod = config.partialStoreHLSVod;
99
100
  }
100
-
101
+ if (config.rollingPDT) {
102
+ this.rollingPDT = config.rollingPDT;
103
+ }
101
104
  if (config.alwaysMapBandwidthByNearest) {
102
105
  this.alwaysMapBandwidthByNearest = config.alwaysMapBandwidthByNearest;
103
106
  }
@@ -1273,7 +1276,8 @@ class Session {
1273
1276
  shouldContainSubtitles: this.use_vtt_subtitles,
1274
1277
  expectedSubtitleTracks: this._subtitleTracks,
1275
1278
  alwaysMapBandwidthByNearest: this.alwaysMapBandwidthByNearest,
1276
- skipSerializeMediaSequences: this.partialStoreHLSVod
1279
+ skipSerializeMediaSequences: this.partialStoreHLSVod,
1280
+ calculatePDT: this.rollingPDT
1277
1281
  };
1278
1282
  newVod = new HLSVod(vodResponse.uri, [], vodResponse.unixTs, vodResponse.offset * 1000, m3u8Header(this._instanceId), hlsOpts);
1279
1283
  if (vodResponse.timedMetadata) {
@@ -1296,7 +1300,7 @@ class Session {
1296
1300
  } else {
1297
1301
  if (vodResponse.type === 'gap') {
1298
1302
  loadPromise = new Promise((resolve, reject) => {
1299
- this._fillGap(null, vodResponse.desiredDuration)
1303
+ this._fillGap(null, vodResponse.desiredDuration, vodResponse.unixTs)
1300
1304
  .then(gapVod => {
1301
1305
  currentVod = gapVod;
1302
1306
  resolve(gapVod);
@@ -1458,7 +1462,8 @@ class Session {
1458
1462
  shouldContainSubtitles: this.use_vtt_subtitles,
1459
1463
  expectedSubtitleTracks: this._subtitleTracks,
1460
1464
  alwaysMapBandwidthByNearest: this.alwaysMapBandwidthByNearest,
1461
- skipSerializeMediaSequences: this.partialStoreHLSVod
1465
+ skipSerializeMediaSequences: this.partialStoreHLSVod,
1466
+ calculatePDT: this.rollingPDT
1462
1467
  };
1463
1468
  newVod = new HLSVod(vodResponse.uri, null, vodResponse.unixTs, vodResponse.offset * 1000, m3u8Header(this._instanceId), hlsOpts);
1464
1469
  if (vodResponse.timedMetadata) {
@@ -1497,7 +1502,7 @@ class Session {
1497
1502
  }
1498
1503
  } else {
1499
1504
  loadPromise = new Promise((resolve, reject) => {
1500
- this._fillGap(currentVod, vodResponse.desiredDuration)
1505
+ this._fillGap(currentVod, vodResponse.desiredDuration, vodResponse.unixTs)
1501
1506
  .then(gapVod => {
1502
1507
  newVod = gapVod;
1503
1508
  resolve(newVod);
@@ -1766,12 +1771,11 @@ class Session {
1766
1771
  });
1767
1772
  }
1768
1773
 
1769
- _loadSlate(afterVod, reps) {
1774
+ _loadSlate(afterVod, reps, unixTs) {
1770
1775
  return new Promise((resolve, reject) => {
1771
1776
  try {
1772
1777
  const slateVod = new HLSRepeatVod(this.slateUri, reps || this.slateRepetitions);
1773
1778
  let hlsVod;
1774
-
1775
1779
  slateVod.load()
1776
1780
  .then(() => {
1777
1781
  const hlsOpts = {
@@ -1782,9 +1786,10 @@ class Session {
1782
1786
  shouldContainSubtitles: this.use_vtt_subtitles,
1783
1787
  expectedSubtitleTracks: this._subtitleTracks,
1784
1788
  alwaysMapBandwidthByNearest: this.alwaysMapBandwidthByNearest,
1785
- skipSerializeMediaSequences: this.partialStoreHLSVod
1789
+ skipSerializeMediaSequences: this.partialStoreHLSVod,
1790
+ calculatePDT: this.rollingPDT
1786
1791
  };
1787
- const timestamp = Date.now();
1792
+ const timestamp = unixTs ? unixTs : Date.now();
1788
1793
  hlsVod = new HLSVod(this.slateUri, null, timestamp, null, m3u8Header(this._instanceId), hlsOpts);
1789
1794
  hlsVod.addMetadata('id', `slate-${timestamp}`);
1790
1795
  hlsVod.addMetadata('start-date', new Date(timestamp).toISOString());
@@ -1882,7 +1887,7 @@ class Session {
1882
1887
  });
1883
1888
  }
1884
1889
 
1885
- _truncateSlate(afterVod, requestedDuration, vodUri) {
1890
+ _truncateSlate(afterVod, requestedDuration, vodUri, unixTs) {
1886
1891
  return new Promise((resolve, reject) => {
1887
1892
  let nexVodUri = null;
1888
1893
  try {
@@ -1896,6 +1901,7 @@ class Session {
1896
1901
 
1897
1902
  slateVod.load()
1898
1903
  .then(() => {
1904
+
1899
1905
  const hlsOpts = {
1900
1906
  sequenceAlwaysContainNewSegments: this.alwaysNewSegments,
1901
1907
  forcedDemuxMode: this.use_demuxed_audio,
@@ -1904,9 +1910,10 @@ class Session {
1904
1910
  shouldContainSubtitles: this.use_vtt_subtitles,
1905
1911
  expectedSubtitleTracks: this._subtitleTracks,
1906
1912
  alwaysMapBandwidthByNearest: this.alwaysMapBandwidthByNearest,
1907
- skipSerializeMediaSequences: this.partialStoreHLSVod
1913
+ skipSerializeMediaSequences: this.partialStoreHLSVod,
1914
+ calculatePDT: this.rollingPDT
1908
1915
  };
1909
- const timestamp = Date.now();
1916
+ const timestamp = unixTs ? unixTs : Date.now();
1910
1917
  hlsVod = new HLSVod(nexVodUri, null, timestamp, null, m3u8Header(this._instanceId), hlsOpts);
1911
1918
  hlsVod.addMetadata('id', `slate-${timestamp}`);
1912
1919
  hlsVod.addMetadata('start-date', new Date(timestamp).toISOString());
@@ -1960,18 +1967,18 @@ class Session {
1960
1967
  });
1961
1968
  }
1962
1969
 
1963
- _fillGap(afterVod, desiredDuration) {
1970
+ _fillGap(afterVod, desiredDuration, unixTs) {
1964
1971
  return new Promise((resolve, reject) => {
1965
1972
  let loadSlatePromise;
1966
1973
  let durationMs;
1967
1974
  if (desiredDuration > this.slateDuration) {
1968
1975
  const reps = Math.floor(desiredDuration / this.slateDuration);
1969
1976
  debug(`[${this._sessionId}]: Trying to fill a gap of ${desiredDuration} milliseconds (${reps} repetitions)`);
1970
- loadSlatePromise = this._loadSlate(afterVod, reps);
1977
+ loadSlatePromise = this._loadSlate(afterVod, reps, unixTs);
1971
1978
  durationMs = (reps || this.slateRepetitions) * this.slateDuration;
1972
1979
  } else {
1973
1980
  debug(`[${this._sessionId}]: Trying to fill a gap of ${desiredDuration} milliseconds by truncating filler slate (${this.slateDuration})`);
1974
- loadSlatePromise = this._truncateSlate(afterVod, desiredDuration / 1000);
1981
+ loadSlatePromise = this._truncateSlate(afterVod, desiredDuration / 1000, null, unixTs);
1975
1982
  durationMs = desiredDuration;
1976
1983
  }
1977
1984
  loadSlatePromise.then(hlsVod => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eyevinn-channel-engine",
3
- "version": "5.0.3",
3
+ "version": "5.0.5",
4
4
  "description": "OTT TV Channel Engine",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -31,9 +31,9 @@
31
31
  "dependencies": {
32
32
  "@eyevinn/hls-repeat": "^0.2.1",
33
33
  "@eyevinn/hls-truncate": "^0.3.3",
34
- "@eyevinn/hls-vodtolive": "^4.1.7",
34
+ "@eyevinn/hls-vodtolive": "^4.1.9",
35
35
  "@eyevinn/m3u8": "^0.5.6",
36
- "@fastify/static": "^5.0.0",
36
+ "@fastify/static": "^8.1.1",
37
37
  "abort-controller": "^3.0.0",
38
38
  "debug": "^3.2.7",
39
39
  "fastify": "^3.29.0",