eyevinn-channel-engine 4.3.4 → 4.3.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.
@@ -16,6 +16,7 @@ export interface ChannelEngineOpts {
16
16
  dummySubtitleEndpoint?: string;
17
17
  subtitleSliceEndpoint?: string;
18
18
  useVTTSubtitles?: boolean;
19
+ vttBasePath?: string;
19
20
  alwaysNewSegments?: boolean;
20
21
  partialStoreHLSVod?: boolean;
21
22
  alwaysMapBandwidthByNearest?: boolean;
@@ -30,6 +31,8 @@ export interface ChannelEngineOpts {
30
31
  volatileKeyTTL?: number;
31
32
  autoCreateSession?: boolean;
32
33
  sessionResetKey?: string;
34
+ keepAliveTimeout?: number;
35
+ sessionEventStream?: boolean;
33
36
  }
34
37
  export interface VodRequest {
35
38
  sessionId: string;
@@ -149,6 +152,7 @@ export declare class ChannelEngine {
149
152
  private adXchangeUri?;
150
153
  private autoCreateSession;
151
154
  private sessionResetKey;
155
+ private sessionEventStream;
152
156
  constructor(assetMgr: IAssetManager, options?: ChannelEngineOpts);
153
157
  updateStreamSwitchAsync(): Promise<void>;
154
158
  updateChannelsAsync(channelMgr: any, options: any): Promise<void>;
@@ -59,8 +59,8 @@ var sessionsLive = {}; // Should be a persistent store...
59
59
  var sessionSwitchers = {}; // Should be a persistent store...
60
60
  var switcherStatus = {}; // Should be a persistent store...
61
61
  var eventStreams = {};
62
- var DefaultDummySubtitleEndpointPath = "/vtt/dummyUrl";
63
- var DefaultSubtitleSpliceEndpointPath = "/vtt/sliceUrl";
62
+ var DefaultDummySubtitleEndpointPath = "/dummyUrl";
63
+ var DefaultSubtitleSpliceEndpointPath = "/sliceUrl";
64
64
  var ScheduleStreamType;
65
65
  (function (ScheduleStreamType) {
66
66
  ScheduleStreamType[ScheduleStreamType["LIVE"] = 1] = "LIVE";
@@ -72,6 +72,7 @@ var ChannelEngine = /** @class */ (function () {
72
72
  var _this = this;
73
73
  this.autoCreateSession = false;
74
74
  this.sessionResetKey = "";
75
+ this.sessionEventStream = false;
75
76
  this.options = options;
76
77
  if (options && options.adCopyMgrUri) {
77
78
  this.adCopyMgrUri = options.adCopyMgrUri;
@@ -84,8 +85,9 @@ var ChannelEngine = /** @class */ (function () {
84
85
  this.useDemuxedAudio = true;
85
86
  }
86
87
  this.useVTTSubtitles = (options && options.useVTTSubtitles) ? options.useVTTSubtitles : false;
87
- this.dummySubtitleEndpoint = (options && options.dummySubtitleEndpoint) ? options.dummySubtitleEndpoint : DefaultDummySubtitleEndpointPath;
88
- this.subtitleSliceEndpoint = (options && options.subtitleSliceEndpoint) ? options.subtitleSliceEndpoint : DefaultSubtitleSpliceEndpointPath;
88
+ var vttBasePath = (options && options.vttBasePath) ? options.vttBasePath : '/vtt';
89
+ this.dummySubtitleEndpoint = (options && options.dummySubtitleEndpoint) ? options.dummySubtitleEndpoint : vttBasePath + DefaultDummySubtitleEndpointPath;
90
+ this.subtitleSliceEndpoint = (options && options.subtitleSliceEndpoint) ? options.subtitleSliceEndpoint : vttBasePath + DefaultSubtitleSpliceEndpointPath;
89
91
  this.sessionResetKey = "";
90
92
  if (options && options.sessionResetKey) {
91
93
  this.sessionResetKey = options.sessionResetKey;
@@ -116,6 +118,10 @@ var ChannelEngine = /** @class */ (function () {
116
118
  this.assetMgr = assetMgr;
117
119
  this.monitorTimer = {};
118
120
  this.server = restify.createServer();
121
+ if (options && options.keepAliveTimeout) {
122
+ this.server.server.keepAliveTimeout = options.keepAliveTimeout;
123
+ this.server.server.headersTimeout = options.keepAliveTimeout + 1000;
124
+ }
119
125
  this.server.use(restify.plugins.queryParser());
120
126
  this.serverStartTime = Date.now();
121
127
  this.instanceId = uuidv4();
@@ -269,8 +275,8 @@ var ChannelEngine = /** @class */ (function () {
269
275
  this.server.get('/health/:sessionId', this._handleSessionHealth.bind(this));
270
276
  this.server.get('/reset', this._handleSessionsReset.bind(this));
271
277
  this.server.get('/reset/:sessionId', this._handleSessionReset.bind(this));
272
- this.server.get(DefaultDummySubtitleEndpointPath, this._handleDummySubtitleEndpoint.bind(this));
273
- this.server.get(DefaultSubtitleSpliceEndpointPath, this._handleSubtitleSliceEndpoint.bind(this));
278
+ this.server.get(vttBasePath + DefaultDummySubtitleEndpointPath, this._handleDummySubtitleEndpoint.bind(this));
279
+ this.server.get(vttBasePath + DefaultSubtitleSpliceEndpointPath, this._handleSubtitleSliceEndpoint.bind(this));
274
280
  this.server.on('NotFound', function (req, res, err, next) {
275
281
  res.header("X-Instance-Id", _this.instanceId + "<".concat(version, ">"));
276
282
  return next();
@@ -468,6 +474,7 @@ var ChannelEngine = /** @class */ (function () {
468
474
  slateRepetitions: channel.slate && channel.slate.repetitions ? channel.slate.repetitions : this.slateRepetitions,
469
475
  slateDuration: channel.slate && channel.slate.duration ? channel.slate.duration : this.slateDuration,
470
476
  cloudWatchMetrics: this.logCloudWatchMetrics,
477
+ sessionEventStream: options.sessionEventStream
471
478
  }, this.sessionStore);
472
479
  sessionsLive[channel.id] = new SessionLive({
473
480
  sessionId: channel.id,
@@ -59,6 +59,7 @@ declare class Session {
59
59
  _subtitleTracks: any;
60
60
  _closedCaptions: any;
61
61
  _noSessionDataTags: any;
62
+ _sessionEventStream: any;
62
63
  slateUri: any;
63
64
  slateRepetitions: any;
64
65
  slateDuration: any;
@@ -56,6 +56,7 @@ var SessionState = require('./session_state.js').SessionState;
56
56
  var PlayheadState = require('./playhead_state.js').PlayheadState;
57
57
  var _a = require('./util.js'), applyFilter = _a.applyFilter, cloudWatchLog = _a.cloudWatchLog, m3u8Header = _a.m3u8Header, logerror = _a.logerror, codecsFromString = _a.codecsFromString;
58
58
  var ChaosMonkey = require('./chaos_monkey.js');
59
+ var EVENT_LIST_LIMIT = 100;
59
60
  var AVERAGE_SEGMENT_DURATION = 3000;
60
61
  var DEFAULT_PLAYHEAD_DIFF_THRESHOLD = 1000;
61
62
  var DEFAULT_MAX_TICK_INTERVAL = 10000;
@@ -164,6 +165,9 @@ var Session = /** @class */ (function () {
164
165
  if (config.noSessionDataTags) {
165
166
  this._noSessionDataTags = config.noSessionDataTags;
166
167
  }
168
+ if (config.sessionEventStream) {
169
+ this._sessionEventStream = config.sessionEventStream;
170
+ }
167
171
  if (config.slateUri) {
168
172
  this.slateUri = config.slateUri;
169
173
  this.slateRepetitions = config.slateRepetitions || 10;
@@ -1687,7 +1691,12 @@ var Session = /** @class */ (function () {
1687
1691
  return this._events.shift();
1688
1692
  };
1689
1693
  Session.prototype.produceEvent = function (event) {
1690
- this._events.push(event);
1694
+ if (this._sessionEventStream) {
1695
+ this._events.push(event);
1696
+ if (this._events.length > EVENT_LIST_LIMIT) {
1697
+ this.consumeEvent();
1698
+ }
1699
+ }
1691
1700
  };
1692
1701
  Session.prototype.hasPlayhead = function () {
1693
1702
  return !this.disabledPlayhead;
@@ -94,6 +94,7 @@ var engineOptions = {
94
94
  defaultSlateUri: "https://maitv-vod.lab.eyevinn.technology/slate-consuo.mp4/master.m3u8",
95
95
  slateRepetitions: 10,
96
96
  redisUrl: process.env.REDIS_URL,
97
+ keepAliveTimeout: process.env.KEEP_ALIVE_TIMEOUT ? parseInt(process.env.KEEP_ALIVE_TIMEOUT) * 1000 : undefined
97
98
  };
98
99
  var engine = new index_1.ChannelEngine(refAssetManager, engineOptions);
99
100
  engine.start();
@@ -100,7 +100,8 @@ var engineOptions = {
100
100
  redisUrl: process.env.REDIS_URL,
101
101
  useDemuxedAudio: true,
102
102
  alwaysNewSegments: false,
103
- useVTTSubtitles: true
103
+ useVTTSubtitles: true,
104
+ vttBasePath: '/subtitles'
104
105
  };
105
106
  var engine = new index_1.ChannelEngine(refAssetManager, engineOptions);
106
107
  engine.start();
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eyevinn-channel-engine",
3
- "version": "4.3.4",
3
+ "version": "4.3.6",
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.0.1",
33
+ "@eyevinn/hls-vodtolive": "^4.1.0",
34
34
  "@eyevinn/m3u8": "^0.5.3",
35
35
  "abort-controller": "^3.0.0",
36
36
  "debug": "^3.2.7",
package/engine/server.ts CHANGED
@@ -24,8 +24,8 @@ const sessionsLive = {}; // Should be a persistent store...
24
24
  const sessionSwitchers = {}; // Should be a persistent store...
25
25
  const switcherStatus = {}; // Should be a persistent store...
26
26
  const eventStreams = {};
27
- const DefaultDummySubtitleEndpointPath = "/vtt/dummyUrl"
28
- const DefaultSubtitleSpliceEndpointPath = "/vtt/sliceUrl"
27
+ const DefaultDummySubtitleEndpointPath = "/dummyUrl"
28
+ const DefaultSubtitleSpliceEndpointPath = "/sliceUrl"
29
29
 
30
30
  export interface ChannelEngineOpts {
31
31
  defaultSlateUri?: string;
@@ -45,6 +45,7 @@ export interface ChannelEngineOpts {
45
45
  dummySubtitleEndpoint?: string;
46
46
  subtitleSliceEndpoint?: string;
47
47
  useVTTSubtitles?: boolean;
48
+ vttBasePath?: string;
48
49
  alwaysNewSegments?: boolean;
49
50
  partialStoreHLSVod?: boolean;
50
51
  alwaysMapBandwidthByNearest?: boolean;
@@ -58,7 +59,9 @@ export interface ChannelEngineOpts {
58
59
  noSessionDataTags?: boolean;
59
60
  volatileKeyTTL?: number;
60
61
  autoCreateSession?: boolean;
61
- sessionResetKey?:string;
62
+ sessionResetKey?: string;
63
+ keepAliveTimeout?: number;
64
+ sessionEventStream?: boolean;
62
65
  }
63
66
 
64
67
  interface StreamerOpts {
@@ -205,6 +208,7 @@ export class ChannelEngine {
205
208
  private adXchangeUri?: string;
206
209
  private autoCreateSession: boolean = false;
207
210
  private sessionResetKey: string = "";
211
+ private sessionEventStream: boolean = false;
208
212
 
209
213
  constructor(assetMgr: IAssetManager, options?: ChannelEngineOpts) {
210
214
  this.options = options;
@@ -220,8 +224,9 @@ export class ChannelEngine {
220
224
  }
221
225
 
222
226
  this.useVTTSubtitles = (options && options.useVTTSubtitles) ? options.useVTTSubtitles : false ;
223
- this.dummySubtitleEndpoint = (options && options.dummySubtitleEndpoint) ? options.dummySubtitleEndpoint : DefaultDummySubtitleEndpointPath;
224
- this.subtitleSliceEndpoint = (options && options.subtitleSliceEndpoint) ? options.subtitleSliceEndpoint : DefaultSubtitleSpliceEndpointPath;
227
+ const vttBasePath = (options && options.vttBasePath) ? options.vttBasePath : '/vtt';
228
+ this.dummySubtitleEndpoint = (options && options.dummySubtitleEndpoint) ? options.dummySubtitleEndpoint : vttBasePath + DefaultDummySubtitleEndpointPath;
229
+ this.subtitleSliceEndpoint = (options && options.subtitleSliceEndpoint) ? options.subtitleSliceEndpoint : vttBasePath + DefaultSubtitleSpliceEndpointPath;
225
230
 
226
231
  this.sessionResetKey = "";
227
232
  if (options && options.sessionResetKey) {
@@ -253,6 +258,10 @@ export class ChannelEngine {
253
258
  this.assetMgr = assetMgr;
254
259
  this.monitorTimer = {};
255
260
  this.server = restify.createServer();
261
+ if (options && options.keepAliveTimeout) {
262
+ this.server.server.keepAliveTimeout = options.keepAliveTimeout;
263
+ this.server.server.headersTimeout = options.keepAliveTimeout + 1000;
264
+ }
256
265
  this.server.use(restify.plugins.queryParser());
257
266
  this.serverStartTime = Date.now();
258
267
  this.instanceId = uuidv4();
@@ -369,8 +378,8 @@ export class ChannelEngine {
369
378
  this.server.get('/health/:sessionId', this._handleSessionHealth.bind(this));
370
379
  this.server.get('/reset', this._handleSessionsReset.bind(this));
371
380
  this.server.get('/reset/:sessionId', this._handleSessionReset.bind(this));
372
- this.server.get(DefaultDummySubtitleEndpointPath, this._handleDummySubtitleEndpoint.bind(this));
373
- this.server.get(DefaultSubtitleSpliceEndpointPath, this._handleSubtitleSliceEndpoint.bind(this));
381
+ this.server.get(vttBasePath + DefaultDummySubtitleEndpointPath, this._handleDummySubtitleEndpoint.bind(this));
382
+ this.server.get(vttBasePath + DefaultSubtitleSpliceEndpointPath, this._handleSubtitleSliceEndpoint.bind(this));
374
383
 
375
384
  this.server.on('NotFound', (req, res, err, next) => {
376
385
  res.header("X-Instance-Id", this.instanceId + `<${version}>`);
@@ -490,6 +499,7 @@ export class ChannelEngine {
490
499
  slateRepetitions: channel.slate && channel.slate.repetitions ? channel.slate.repetitions : this.slateRepetitions,
491
500
  slateDuration: channel.slate && channel.slate.duration ? channel.slate.duration : this.slateDuration,
492
501
  cloudWatchMetrics: this.logCloudWatchMetrics,
502
+ sessionEventStream: options.sessionEventStream
493
503
  }, this.sessionStore);
494
504
 
495
505
  sessionsLive[channel.id] = new SessionLive({
package/engine/session.js CHANGED
@@ -12,6 +12,7 @@ const { PlayheadState } = require('./playhead_state.js');
12
12
  const { applyFilter, cloudWatchLog, m3u8Header, logerror, codecsFromString } = require('./util.js');
13
13
  const ChaosMonkey = require('./chaos_monkey.js');
14
14
 
15
+ const EVENT_LIST_LIMIT = 100;
15
16
  const AVERAGE_SEGMENT_DURATION = 3000;
16
17
  const DEFAULT_PLAYHEAD_DIFF_THRESHOLD = 1000;
17
18
  const DEFAULT_MAX_TICK_INTERVAL = 10000;
@@ -128,6 +129,9 @@ class Session {
128
129
  if (config.noSessionDataTags) {
129
130
  this._noSessionDataTags = config.noSessionDataTags;
130
131
  }
132
+ if (config.sessionEventStream) {
133
+ this._sessionEventStream = config.sessionEventStream;
134
+ }
131
135
  if (config.slateUri) {
132
136
  this.slateUri = config.slateUri;
133
137
  this.slateRepetitions = config.slateRepetitions || 10;
@@ -1246,7 +1250,12 @@ class Session {
1246
1250
  }
1247
1251
 
1248
1252
  produceEvent(event) {
1249
- this._events.push(event);
1253
+ if (this._sessionEventStream) {
1254
+ this._events.push(event);
1255
+ if (this._events.length > EVENT_LIST_LIMIT) {
1256
+ this.consumeEvent();
1257
+ }
1258
+ }
1250
1259
  }
1251
1260
 
1252
1261
  hasPlayhead() {
@@ -106,6 +106,7 @@ const engineOptions: ChannelEngineOpts = {
106
106
  "https://maitv-vod.lab.eyevinn.technology/slate-consuo.mp4/master.m3u8",
107
107
  slateRepetitions: 10,
108
108
  redisUrl: process.env.REDIS_URL,
109
+ keepAliveTimeout: process.env.KEEP_ALIVE_TIMEOUT ? parseInt(process.env.KEEP_ALIVE_TIMEOUT) * 1000: undefined
109
110
  };
110
111
 
111
112
  const engine = new ChannelEngine(refAssetManager, engineOptions);
package/examples/demux.ts CHANGED
@@ -112,7 +112,8 @@ const engineOptions: ChannelEngineOpts = {
112
112
  redisUrl: process.env.REDIS_URL,
113
113
  useDemuxedAudio: true,
114
114
  alwaysNewSegments: false,
115
- useVTTSubtitles: true
115
+ useVTTSubtitles: true,
116
+ vttBasePath: '/subtitles'
116
117
  };
117
118
 
118
119
  const engine = new ChannelEngine(refAssetManager, engineOptions);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eyevinn-channel-engine",
3
- "version": "4.3.4",
3
+ "version": "4.3.6",
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.0.1",
33
+ "@eyevinn/hls-vodtolive": "^4.1.0",
34
34
  "@eyevinn/m3u8": "^0.5.3",
35
35
  "abort-controller": "^3.0.0",
36
36
  "debug": "^3.2.7",