eyevinn-channel-engine 4.3.1 → 4.3.3-rc.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Dockerfile +3 -2
- package/dist/engine/memcached_state_store.d.ts +1 -0
- package/dist/engine/memcached_state_store.js +8 -0
- package/dist/engine/memory_state_store.d.ts +2 -0
- package/dist/engine/memory_state_store.js +29 -0
- package/dist/engine/redis_state_store.d.ts +1 -0
- package/dist/engine/redis_state_store.js +19 -4
- package/dist/engine/server.d.ts +3 -0
- package/dist/engine/server.js +82 -3
- package/dist/engine/session.d.ts +1 -1
- package/dist/engine/session.js +12 -3
- package/dist/engine/shared_state_store.d.ts +1 -0
- package/dist/engine/shared_state_store.js +12 -0
- package/dist/examples/default.js +8 -17
- package/dist/package.json +2 -1
- package/dist/server-demux.d.ts +1 -0
- package/dist/server-demux.js +107 -0
- package/dist/server-drm.d.ts +1 -0
- package/dist/server-drm.js +114 -0
- package/dist/server-livemix.d.ts +1 -0
- package/dist/server-livemix.js +196 -0
- package/dist/server-multicodec.d.ts +1 -0
- package/dist/server-multicodec.js +96 -0
- package/dist/server.d.ts +1 -0
- package/dist/server.js +101 -0
- package/engine/memcached_state_store.js +4 -0
- package/engine/memory_state_store.js +18 -2
- package/engine/redis_state_store.js +14 -9
- package/engine/server.ts +75 -3
- package/engine/session.js +7 -3
- package/engine/shared_state_store.js +4 -0
- package/examples/default.ts +8 -18
- package/package.json +2 -1
- package/validation_data.json +2139 -0
package/Dockerfile
CHANGED
|
@@ -5,6 +5,7 @@ declare class MemcachedStateStore {
|
|
|
5
5
|
client: any;
|
|
6
6
|
initAsync(id: any, initData: any): Promise<{}>;
|
|
7
7
|
resetAsync(id: any, initData: any): Promise<void>;
|
|
8
|
+
resetAllAsync(): Promise<void>;
|
|
8
9
|
getAsync(id: any, key: any): Promise<any>;
|
|
9
10
|
setAsync(id: any, key: any, value: any): Promise<any>;
|
|
10
11
|
setVolatileAsync(id: any, key: any, value: any): Promise<void>;
|
|
@@ -112,6 +112,14 @@ var MemcachedStateStore = /** @class */ (function () {
|
|
|
112
112
|
});
|
|
113
113
|
});
|
|
114
114
|
};
|
|
115
|
+
MemcachedStateStore.prototype.resetAllAsync = function () {
|
|
116
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
117
|
+
return __generator(this, function (_a) {
|
|
118
|
+
console.error("Shared Storage Reset Failed.\nMemcache-client: Flush All Command Not Implemented Yet");
|
|
119
|
+
return [2 /*return*/];
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
};
|
|
115
123
|
MemcachedStateStore.prototype.getAsync = function (id, key) {
|
|
116
124
|
return __awaiter(this, void 0, void 0, function () {
|
|
117
125
|
var storeKey, data;
|
|
@@ -4,6 +4,8 @@ declare class MemoryStateStore {
|
|
|
4
4
|
sharedStates: {};
|
|
5
5
|
globalSharedStates: {};
|
|
6
6
|
initAsync(id: any, initData: any): Promise<any>;
|
|
7
|
+
resetAsync(id: any, initData: any): Promise<void>;
|
|
8
|
+
resetAllAsync(): Promise<void>;
|
|
7
9
|
getAsync(id: any, key: any): Promise<any>;
|
|
8
10
|
setAsync(id: any, key: any, value: any): Promise<any>;
|
|
9
11
|
setVolatileAsync(id: any, key: any, value: any): Promise<any>;
|
|
@@ -54,6 +54,29 @@ var MemoryStateStore = /** @class */ (function () {
|
|
|
54
54
|
});
|
|
55
55
|
});
|
|
56
56
|
};
|
|
57
|
+
MemoryStateStore.prototype.resetAsync = function (id, initData) {
|
|
58
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
59
|
+
return __generator(this, function (_a) {
|
|
60
|
+
switch (_a.label) {
|
|
61
|
+
case 0:
|
|
62
|
+
this.sharedStates[id] = null;
|
|
63
|
+
return [4 /*yield*/, this.initAsync(id, initData)];
|
|
64
|
+
case 1:
|
|
65
|
+
_a.sent();
|
|
66
|
+
return [2 /*return*/];
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
};
|
|
71
|
+
MemoryStateStore.prototype.resetAllAsync = function () {
|
|
72
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
73
|
+
return __generator(this, function (_a) {
|
|
74
|
+
this.sharedStates = {};
|
|
75
|
+
this.globalSharedStates = {};
|
|
76
|
+
return [2 /*return*/];
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
};
|
|
57
80
|
MemoryStateStore.prototype.getAsync = function (id, key) {
|
|
58
81
|
return __awaiter(this, void 0, void 0, function () {
|
|
59
82
|
var value;
|
|
@@ -62,6 +85,9 @@ var MemoryStateStore = /** @class */ (function () {
|
|
|
62
85
|
value = this.globalSharedStates[key];
|
|
63
86
|
}
|
|
64
87
|
else {
|
|
88
|
+
if (!this.sharedStates[id]) {
|
|
89
|
+
return [2 /*return*/, null];
|
|
90
|
+
}
|
|
65
91
|
value = this.sharedStates[id][key];
|
|
66
92
|
}
|
|
67
93
|
return [2 /*return*/, value];
|
|
@@ -75,6 +101,9 @@ var MemoryStateStore = /** @class */ (function () {
|
|
|
75
101
|
this.globalSharedStates[key] = value;
|
|
76
102
|
}
|
|
77
103
|
else {
|
|
104
|
+
if (!this.sharedStates[id]) {
|
|
105
|
+
this.sharedStates[id] = {};
|
|
106
|
+
}
|
|
78
107
|
this.sharedStates[id][key] = value;
|
|
79
108
|
return [2 /*return*/, this.sharedStates[id][key]];
|
|
80
109
|
}
|
|
@@ -6,6 +6,7 @@ declare class RedisStateStore {
|
|
|
6
6
|
client: any;
|
|
7
7
|
initAsync(id: any, initData: any): Promise<{}>;
|
|
8
8
|
resetAsync(id: any, initData: any): Promise<void>;
|
|
9
|
+
resetAllAsync(): Promise<void>;
|
|
9
10
|
getAsync(id: any, key: any): Promise<any>;
|
|
10
11
|
setAsync(id: any, key: any, value: any): Promise<any>;
|
|
11
12
|
setVolatileAsync(id: any, key: any, value: any): Promise<any>;
|
|
@@ -34,7 +34,7 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
|
34
34
|
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
35
35
|
}
|
|
36
36
|
};
|
|
37
|
-
var
|
|
37
|
+
var Redis = require("ioredis");
|
|
38
38
|
var debug = require("debug")("redis-state-store");
|
|
39
39
|
var DEFAULT_VOLATILE_KEY_TTL = 5; // Timeout so it should not expire within one normal increment iteration (in seconds)
|
|
40
40
|
var RedisStateStore = /** @class */ (function () {
|
|
@@ -50,7 +50,7 @@ var RedisStateStore = /** @class */ (function () {
|
|
|
50
50
|
debug("Overriding default, volatileKeyTTL=".concat(opts.volatileKeyTTL, "s"));
|
|
51
51
|
this.volatileKeyTTL = opts.volatileKeyTTL;
|
|
52
52
|
}
|
|
53
|
-
this.client =
|
|
53
|
+
this.client = new Redis(opts.redisUrl);
|
|
54
54
|
}
|
|
55
55
|
RedisStateStore.prototype.initAsync = function (id, initData) {
|
|
56
56
|
return __awaiter(this, void 0, void 0, function () {
|
|
@@ -104,6 +104,21 @@ var RedisStateStore = /** @class */ (function () {
|
|
|
104
104
|
});
|
|
105
105
|
};
|
|
106
106
|
RedisStateStore.prototype.resetAsync = function (id, initData) {
|
|
107
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
108
|
+
return __generator(this, function (_a) {
|
|
109
|
+
switch (_a.label) {
|
|
110
|
+
case 0: return [4 /*yield*/, this.setAsync(id, "_initiated", false)];
|
|
111
|
+
case 1:
|
|
112
|
+
_a.sent();
|
|
113
|
+
return [4 /*yield*/, this.initAsync(id, initData)];
|
|
114
|
+
case 2:
|
|
115
|
+
_a.sent();
|
|
116
|
+
return [2 /*return*/];
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
};
|
|
121
|
+
RedisStateStore.prototype.resetAllAsync = function () {
|
|
107
122
|
return __awaiter(this, void 0, void 0, function () {
|
|
108
123
|
var resetAsync;
|
|
109
124
|
var _this = this;
|
|
@@ -170,7 +185,7 @@ var RedisStateStore = /** @class */ (function () {
|
|
|
170
185
|
setAsync = new Promise(function (resolve, reject) {
|
|
171
186
|
_this.client.set(storeKey, JSON.stringify(value), function (err, res) {
|
|
172
187
|
var ioTimeMs = Date.now() - startMs;
|
|
173
|
-
debug("REDIS set ".concat(storeKey, ": ").concat(res, " (").concat(ioTimeMs, "ms) ").concat(ioTimeMs > 1000 ?
|
|
188
|
+
debug("REDIS set ".concat(storeKey, ": ").concat(res, " (").concat(ioTimeMs, "ms) ").concat(ioTimeMs > 1000 ? "REDISSLOW!" : ""));
|
|
174
189
|
if (!err) {
|
|
175
190
|
resolve(value);
|
|
176
191
|
}
|
|
@@ -226,7 +241,7 @@ var RedisStateStore = /** @class */ (function () {
|
|
|
226
241
|
delAsync = new Promise(function (resolve, reject) {
|
|
227
242
|
_this.client.del(storeKey, function (err, res) {
|
|
228
243
|
var ioTimeMs = Date.now() - startMs;
|
|
229
|
-
debug("REDIS remove ".concat(storeKey, ": (").concat(ioTimeMs, "ms) ").concat(ioTimeMs > 1000 ?
|
|
244
|
+
debug("REDIS remove ".concat(storeKey, ": (").concat(ioTimeMs, "ms) ").concat(ioTimeMs > 1000 ? "REDISSLOW!" : ""));
|
|
230
245
|
if (!err) {
|
|
231
246
|
resolve();
|
|
232
247
|
}
|
package/dist/engine/server.d.ts
CHANGED
|
@@ -29,6 +29,7 @@ export interface ChannelEngineOpts {
|
|
|
29
29
|
noSessionDataTags?: boolean;
|
|
30
30
|
volatileKeyTTL?: number;
|
|
31
31
|
autoCreateSession?: boolean;
|
|
32
|
+
sessionResetKey?: string;
|
|
32
33
|
}
|
|
33
34
|
export interface VodRequest {
|
|
34
35
|
sessionId: string;
|
|
@@ -147,6 +148,7 @@ export declare class ChannelEngine {
|
|
|
147
148
|
private adCopyMgrUri?;
|
|
148
149
|
private adXchangeUri?;
|
|
149
150
|
private autoCreateSession;
|
|
151
|
+
private sessionResetKey;
|
|
150
152
|
constructor(assetMgr: IAssetManager, options?: ChannelEngineOpts);
|
|
151
153
|
updateStreamSwitchAsync(): Promise<void>;
|
|
152
154
|
updateChannelsAsync(channelMgr: any, options: any): Promise<void>;
|
|
@@ -172,6 +174,7 @@ export declare class ChannelEngine {
|
|
|
172
174
|
_handleStatus(req: any, res: any, next: any): Promise<void>;
|
|
173
175
|
_handleAggregatedSessionHealth(req: any, res: any, next: any): Promise<void>;
|
|
174
176
|
_handleSessionHealth(req: any, res: any, next: any): Promise<void>;
|
|
177
|
+
_handleSessionsReset(req: any, res: any, next: any): Promise<void>;
|
|
175
178
|
_handleSessionReset(req: any, res: any, next: any): Promise<void>;
|
|
176
179
|
_gracefulErrorHandler(errMsg: any): any;
|
|
177
180
|
_errorHandler(errMsg: any): any;
|
package/dist/engine/server.js
CHANGED
|
@@ -71,6 +71,7 @@ var ChannelEngine = /** @class */ (function () {
|
|
|
71
71
|
function ChannelEngine(assetMgr, options) {
|
|
72
72
|
var _this = this;
|
|
73
73
|
this.autoCreateSession = false;
|
|
74
|
+
this.sessionResetKey = "";
|
|
74
75
|
this.options = options;
|
|
75
76
|
if (options && options.adCopyMgrUri) {
|
|
76
77
|
this.adCopyMgrUri = options.adCopyMgrUri;
|
|
@@ -85,6 +86,10 @@ var ChannelEngine = /** @class */ (function () {
|
|
|
85
86
|
this.useVTTSubtitles = (options && options.useVTTSubtitles) ? options.useVTTSubtitles : false;
|
|
86
87
|
this.dummySubtitleEndpoint = (options && options.dummySubtitleEndpoint) ? options.dummySubtitleEndpoint : DefaultDummySubtitleEndpointPath;
|
|
87
88
|
this.subtitleSliceEndpoint = (options && options.subtitleSliceEndpoint) ? options.subtitleSliceEndpoint : DefaultSubtitleSpliceEndpointPath;
|
|
89
|
+
this.sessionResetKey = "";
|
|
90
|
+
if (options && options.sessionResetKey) {
|
|
91
|
+
this.sessionResetKey = options.sessionResetKey;
|
|
92
|
+
}
|
|
88
93
|
this.alwaysNewSegments = false;
|
|
89
94
|
if (options && options.alwaysNewSegments) {
|
|
90
95
|
this.alwaysNewSegments = true;
|
|
@@ -262,7 +267,8 @@ var ChannelEngine = /** @class */ (function () {
|
|
|
262
267
|
this.server.get('/status/:sessionId', this._handleStatus.bind(this));
|
|
263
268
|
this.server.get('/health', this._handleAggregatedSessionHealth.bind(this));
|
|
264
269
|
this.server.get('/health/:sessionId', this._handleSessionHealth.bind(this));
|
|
265
|
-
this.server.get('/reset', this.
|
|
270
|
+
this.server.get('/reset', this._handleSessionsReset.bind(this));
|
|
271
|
+
this.server.get('/reset/:sessionId', this._handleSessionReset.bind(this));
|
|
266
272
|
this.server.get(DefaultDummySubtitleEndpointPath, this._handleDummySubtitleEndpoint.bind(this));
|
|
267
273
|
this.server.get(DefaultSubtitleSpliceEndpointPath, this._handleSubtitleSliceEndpoint.bind(this));
|
|
268
274
|
this.server.on('NotFound', function (req, res, err, next) {
|
|
@@ -445,6 +451,7 @@ var ChannelEngine = /** @class */ (function () {
|
|
|
445
451
|
subtitleSliceEndpoint: this.subtitleSliceEndpoint,
|
|
446
452
|
useVTTSubtitles: this.useVTTSubtitles,
|
|
447
453
|
alwaysNewSegments: options.alwaysNewSegments,
|
|
454
|
+
sessionResetKey: options.sessionResetKey,
|
|
448
455
|
partialStoreHLSVod: options.partialStoreHLSVod,
|
|
449
456
|
alwaysMapBandwidthByNearest: options.alwaysMapBandwidthByNearest,
|
|
450
457
|
noSessionDataTags: options.noSessionDataTags,
|
|
@@ -1013,7 +1020,7 @@ var ChannelEngine = /** @class */ (function () {
|
|
|
1013
1020
|
return __generator(this, function (_a) {
|
|
1014
1021
|
debug("req.url=".concat(req.url));
|
|
1015
1022
|
try {
|
|
1016
|
-
body = "WEBVTT\nX-TIMESTAMP-MAP=MPEGTS:0,LOCAL:00:00:00.000";
|
|
1023
|
+
body = "WEBVTT\nX-TIMESTAMP-MAP=MPEGTS:0,LOCAL:00:00:00.000\n\n";
|
|
1017
1024
|
res.sendRaw(200, Buffer.from(body, 'utf8'), {
|
|
1018
1025
|
"Content-Type": "text/vtt",
|
|
1019
1026
|
"Access-Control-Allow-Origin": "*",
|
|
@@ -1275,13 +1282,22 @@ var ChannelEngine = /** @class */ (function () {
|
|
|
1275
1282
|
});
|
|
1276
1283
|
});
|
|
1277
1284
|
};
|
|
1278
|
-
ChannelEngine.prototype.
|
|
1285
|
+
ChannelEngine.prototype._handleSessionsReset = function (req, res, next) {
|
|
1279
1286
|
return __awaiter(this, void 0, void 0, function () {
|
|
1280
1287
|
var sessionResets, _i, _a, sessionId, session, sessionLive, err;
|
|
1281
1288
|
return __generator(this, function (_b) {
|
|
1282
1289
|
switch (_b.label) {
|
|
1283
1290
|
case 0:
|
|
1284
1291
|
debug("req.url=".concat(req.url));
|
|
1292
|
+
if (this.sessionResetKey && req.query.key !== this.sessionResetKey) {
|
|
1293
|
+
res.sendRaw(403, JSON.stringify({ "message": "Invalid Session-Reset-Key" }), {
|
|
1294
|
+
"Content-Type": "application/json",
|
|
1295
|
+
"Access-Control-Allow-Origin": "*",
|
|
1296
|
+
"Cache-Control": "no-cache",
|
|
1297
|
+
});
|
|
1298
|
+
next();
|
|
1299
|
+
return [2 /*return*/];
|
|
1300
|
+
}
|
|
1285
1301
|
sessionResets = [];
|
|
1286
1302
|
_i = 0, _a = Object.keys(sessions);
|
|
1287
1303
|
_b.label = 1;
|
|
@@ -1314,6 +1330,69 @@ var ChannelEngine = /** @class */ (function () {
|
|
|
1314
1330
|
});
|
|
1315
1331
|
});
|
|
1316
1332
|
};
|
|
1333
|
+
ChannelEngine.prototype._handleSessionReset = function (req, res, next) {
|
|
1334
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
1335
|
+
var sessionId, sessionResets, session, sessionLive, e_1, err;
|
|
1336
|
+
return __generator(this, function (_a) {
|
|
1337
|
+
switch (_a.label) {
|
|
1338
|
+
case 0:
|
|
1339
|
+
debug("req.url=".concat(req.url));
|
|
1340
|
+
if (this.sessionResetKey && req.query.key !== this.sessionResetKey) {
|
|
1341
|
+
res.sendRaw(403, JSON.stringify({ "message": "Invalid Session-Reset-Key" }), {
|
|
1342
|
+
"Content-Type": "application/json",
|
|
1343
|
+
"Access-Control-Allow-Origin": "*",
|
|
1344
|
+
"Cache-Control": "no-cache",
|
|
1345
|
+
});
|
|
1346
|
+
next();
|
|
1347
|
+
return [2 /*return*/];
|
|
1348
|
+
}
|
|
1349
|
+
_a.label = 1;
|
|
1350
|
+
case 1:
|
|
1351
|
+
_a.trys.push([1, 5, , 6]);
|
|
1352
|
+
sessionId = void 0;
|
|
1353
|
+
if (req.params && req.params.sessionId) {
|
|
1354
|
+
sessionId = req.params.sessionId;
|
|
1355
|
+
}
|
|
1356
|
+
sessionResets = [];
|
|
1357
|
+
session = sessions[sessionId];
|
|
1358
|
+
sessionLive = sessionsLive[sessionId];
|
|
1359
|
+
if (!(session && sessionLive)) return [3 /*break*/, 3];
|
|
1360
|
+
return [4 /*yield*/, session.resetAsync(sessionId)];
|
|
1361
|
+
case 2:
|
|
1362
|
+
_a.sent();
|
|
1363
|
+
sessionResets.push(sessionId);
|
|
1364
|
+
return [3 /*break*/, 4];
|
|
1365
|
+
case 3:
|
|
1366
|
+
res.sendRaw(400, JSON.stringify({ "message": "Invalid Session ID" }), {
|
|
1367
|
+
"Content-Type": "application/json",
|
|
1368
|
+
"Access-Control-Allow-Origin": "*",
|
|
1369
|
+
"Cache-Control": "no-cache",
|
|
1370
|
+
});
|
|
1371
|
+
next();
|
|
1372
|
+
return [2 /*return*/];
|
|
1373
|
+
case 4:
|
|
1374
|
+
res.sendRaw(200, JSON.stringify({ "status": "ok", "instanceId": this.instanceId, "resets": sessionResets }), {
|
|
1375
|
+
"Content-Type": "application/json",
|
|
1376
|
+
"Access-Control-Allow-Origin": "*",
|
|
1377
|
+
"Cache-Control": "no-cache",
|
|
1378
|
+
});
|
|
1379
|
+
next();
|
|
1380
|
+
return [3 /*break*/, 6];
|
|
1381
|
+
case 5:
|
|
1382
|
+
e_1 = _a.sent();
|
|
1383
|
+
res.sendRaw(500, JSON.stringify({ "error": e_1 }), {
|
|
1384
|
+
"Content-Type": "application/json",
|
|
1385
|
+
"Access-Control-Allow-Origin": "*",
|
|
1386
|
+
"Cache-Control": "no-cache",
|
|
1387
|
+
});
|
|
1388
|
+
err = new errs.NotFoundError('Session Reset Failed');
|
|
1389
|
+
next(err);
|
|
1390
|
+
return [3 /*break*/, 6];
|
|
1391
|
+
case 6: return [2 /*return*/];
|
|
1392
|
+
}
|
|
1393
|
+
});
|
|
1394
|
+
});
|
|
1395
|
+
};
|
|
1317
1396
|
ChannelEngine.prototype._gracefulErrorHandler = function (errMsg) {
|
|
1318
1397
|
console.error(errMsg);
|
|
1319
1398
|
var err = new errs.NotFoundError(errMsg);
|
package/dist/engine/session.d.ts
CHANGED
|
@@ -83,7 +83,7 @@ declare class Session {
|
|
|
83
83
|
} | {
|
|
84
84
|
sessionId: any;
|
|
85
85
|
}>;
|
|
86
|
-
resetAsync(): Promise<void>;
|
|
86
|
+
resetAsync(id: any): Promise<void>;
|
|
87
87
|
getSessionState(): Promise<any>;
|
|
88
88
|
getTruncatedVodSegments(vodUri: any, duration: any): Promise<any>;
|
|
89
89
|
setCurrentMediaSequenceSegments(segments: any, mSeqOffset: any, reloadBehind: any): Promise<void>;
|
package/dist/engine/session.js
CHANGED
|
@@ -454,15 +454,24 @@ var Session = /** @class */ (function () {
|
|
|
454
454
|
});
|
|
455
455
|
});
|
|
456
456
|
};
|
|
457
|
-
Session.prototype.resetAsync = function () {
|
|
457
|
+
Session.prototype.resetAsync = function (id) {
|
|
458
458
|
return __awaiter(this, void 0, void 0, function () {
|
|
459
459
|
return __generator(this, function (_a) {
|
|
460
460
|
switch (_a.label) {
|
|
461
|
-
case 0:
|
|
461
|
+
case 0:
|
|
462
|
+
if (!id) return [3 /*break*/, 3];
|
|
463
|
+
return [4 /*yield*/, this._sessionStateStore.reset(id)];
|
|
462
464
|
case 1:
|
|
463
465
|
_a.sent();
|
|
464
|
-
return [4 /*yield*/, this._playheadStateStore.reset(
|
|
466
|
+
return [4 /*yield*/, this._playheadStateStore.reset(id)];
|
|
465
467
|
case 2:
|
|
468
|
+
_a.sent();
|
|
469
|
+
_a.label = 3;
|
|
470
|
+
case 3: return [4 /*yield*/, this._sessionStateStore.resetAll()];
|
|
471
|
+
case 4:
|
|
472
|
+
_a.sent();
|
|
473
|
+
return [4 /*yield*/, this._playheadStateStore.resetAll()];
|
|
474
|
+
case 5:
|
|
466
475
|
_a.sent();
|
|
467
476
|
return [2 /*return*/];
|
|
468
477
|
}
|
|
@@ -10,6 +10,7 @@ declare class SharedStateStore {
|
|
|
10
10
|
isShared(): boolean;
|
|
11
11
|
init(id: any): Promise<void>;
|
|
12
12
|
reset(id: any): Promise<void>;
|
|
13
|
+
resetAll(): Promise<void>;
|
|
13
14
|
get(id: any, key: any): Promise<any>;
|
|
14
15
|
set(id: any, key: any, value: any): Promise<any>;
|
|
15
16
|
setVolatile(id: any, key: any, value: any): Promise<any>;
|
|
@@ -87,6 +87,18 @@ var SharedStateStore = /** @class */ (function () {
|
|
|
87
87
|
});
|
|
88
88
|
});
|
|
89
89
|
};
|
|
90
|
+
SharedStateStore.prototype.resetAll = function () {
|
|
91
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
92
|
+
return __generator(this, function (_a) {
|
|
93
|
+
switch (_a.label) {
|
|
94
|
+
case 0: return [4 /*yield*/, this.store.resetAllAsync()];
|
|
95
|
+
case 1:
|
|
96
|
+
_a.sent();
|
|
97
|
+
return [2 /*return*/];
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
};
|
|
90
102
|
SharedStateStore.prototype.get = function (id, key) {
|
|
91
103
|
return __awaiter(this, void 0, void 0, function () {
|
|
92
104
|
var data;
|
package/dist/examples/default.js
CHANGED
|
@@ -4,26 +4,29 @@
|
|
|
4
4
|
*/
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
var index_1 = require("../index");
|
|
7
|
-
var STITCH_ENDPOINT = process.env.STITCH_ENDPOINT ||
|
|
8
|
-
"http://lambda.eyevinn.technology/stitch/master.m3u8";
|
|
9
7
|
var RefAssetManager = /** @class */ (function () {
|
|
10
8
|
function RefAssetManager(opts) {
|
|
11
9
|
this.assets = {
|
|
12
10
|
1: [
|
|
13
11
|
{
|
|
14
12
|
id: 1,
|
|
13
|
+
title: "Streaming Tech TV+",
|
|
14
|
+
uri: "https://lab.cdn.eyevinn.technology/stswetvplus-promo-2023-5GBm231Mkz.mov/manifest.m3u8",
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
id: 2,
|
|
15
18
|
title: "Tears of Steel",
|
|
16
19
|
uri: "https://maitv-vod.lab.eyevinn.technology/tearsofsteel_4k.mov/master.m3u8",
|
|
17
20
|
},
|
|
18
21
|
{
|
|
19
|
-
id:
|
|
22
|
+
id: 3,
|
|
20
23
|
title: "VINN",
|
|
21
24
|
uri: "https://maitv-vod.lab.eyevinn.technology/VINN.mp4/master.m3u8",
|
|
22
25
|
},
|
|
23
26
|
],
|
|
24
27
|
};
|
|
25
28
|
this.pos = {
|
|
26
|
-
1:
|
|
29
|
+
1: 0,
|
|
27
30
|
};
|
|
28
31
|
}
|
|
29
32
|
/**
|
|
@@ -44,22 +47,10 @@ var RefAssetManager = /** @class */ (function () {
|
|
|
44
47
|
if (_this.pos[channelId] > _this.assets[channelId].length - 1) {
|
|
45
48
|
_this.pos[channelId] = 0;
|
|
46
49
|
}
|
|
47
|
-
var payload = {
|
|
48
|
-
uri: vod.uri,
|
|
49
|
-
breaks: [
|
|
50
|
-
{
|
|
51
|
-
pos: 100,
|
|
52
|
-
duration: 15 * 1000,
|
|
53
|
-
url: "https://maitv-vod.lab.eyevinn.technology/ads/6cd7d768_e214_4ebc_9f14_7ed89710115e_mp4/master.m3u8",
|
|
54
|
-
},
|
|
55
|
-
],
|
|
56
|
-
};
|
|
57
|
-
var buff = Buffer.from(JSON.stringify(payload));
|
|
58
|
-
var encodedPayload = buff.toString("base64");
|
|
59
50
|
var vodResponse = {
|
|
60
51
|
id: vod.id,
|
|
61
52
|
title: vod.title,
|
|
62
|
-
uri:
|
|
53
|
+
uri: vod.uri,
|
|
63
54
|
};
|
|
64
55
|
resolve(vodResponse);
|
|
65
56
|
}
|
package/dist/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eyevinn-channel-engine",
|
|
3
|
-
"version": "4.3.
|
|
3
|
+
"version": "4.3.3-rc.0",
|
|
4
4
|
"description": "OTT TV Channel Engine",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -34,6 +34,7 @@
|
|
|
34
34
|
"@eyevinn/m3u8": "^0.5.3",
|
|
35
35
|
"abort-controller": "^3.0.0",
|
|
36
36
|
"debug": "^3.2.7",
|
|
37
|
+
"ioredis": "^5.3.2",
|
|
37
38
|
"memcache-client": "^0.10.1",
|
|
38
39
|
"nock": "^13.1.1",
|
|
39
40
|
"node-fetch": "^2.6.1",
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* Reference implementation of Channel Engine library using demuxed VOD assets.
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
var index_1 = require("./index");
|
|
7
|
+
var RefAssetManager = /** @class */ (function () {
|
|
8
|
+
function RefAssetManager(opts) {
|
|
9
|
+
this.assets = {
|
|
10
|
+
1: [
|
|
11
|
+
{
|
|
12
|
+
id: 1,
|
|
13
|
+
title: "Elephants dream",
|
|
14
|
+
uri: "https://playertest.longtailvideo.com/adaptive/elephants_dream_v4/index.m3u8",
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
id: 2,
|
|
18
|
+
title: "Test HLS Bird noises (1m10s)",
|
|
19
|
+
uri: "https://mtoczko.github.io/hls-test-streams/test-audio-pdt/playlist.m3u8",
|
|
20
|
+
},
|
|
21
|
+
],
|
|
22
|
+
};
|
|
23
|
+
this.pos = {
|
|
24
|
+
1: 0,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
*
|
|
29
|
+
* @param {Object} vodRequest
|
|
30
|
+
* {
|
|
31
|
+
* sessionId,
|
|
32
|
+
* category,
|
|
33
|
+
* playlistId
|
|
34
|
+
* }
|
|
35
|
+
*/
|
|
36
|
+
RefAssetManager.prototype.getNextVod = function (vodRequest) {
|
|
37
|
+
var _this = this;
|
|
38
|
+
return new Promise(function (resolve, reject) {
|
|
39
|
+
var channelId = vodRequest.playlistId;
|
|
40
|
+
if (_this.assets[channelId]) {
|
|
41
|
+
var vod = _this.assets[channelId][_this.pos[channelId]++];
|
|
42
|
+
if (_this.pos[channelId] > _this.assets[channelId].length - 1) {
|
|
43
|
+
_this.pos[channelId] = 0;
|
|
44
|
+
}
|
|
45
|
+
resolve(vod);
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
reject("Invalid channelId provided");
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
};
|
|
52
|
+
return RefAssetManager;
|
|
53
|
+
}());
|
|
54
|
+
var RefChannelManager = /** @class */ (function () {
|
|
55
|
+
function RefChannelManager() {
|
|
56
|
+
}
|
|
57
|
+
RefChannelManager.prototype.getChannels = function () {
|
|
58
|
+
return [{ id: "1", profile: this._getProfile(), audioTracks: this._getAudioTracks(), subtitleTracks: this._getSubtitleTracks() }];
|
|
59
|
+
};
|
|
60
|
+
RefChannelManager.prototype._getProfile = function () {
|
|
61
|
+
return [
|
|
62
|
+
{
|
|
63
|
+
bw: 7934000,
|
|
64
|
+
codecs: "avc1.4d001f,mp4a.40.2",
|
|
65
|
+
resolution: [2880, 1440],
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
bw: 7514000,
|
|
69
|
+
codecs: "avc1.4d001f,mp4a.40.2",
|
|
70
|
+
resolution: [1920, 1080],
|
|
71
|
+
},
|
|
72
|
+
{ bw: 7134000, codecs: "avc1.4d001f,mp4a.40.2", resolution: [1280, 720] },
|
|
73
|
+
{ bw: 6134000, codecs: "avc1.4d001f,mp4a.40.2", resolution: [1024, 458] },
|
|
74
|
+
{ bw: 2323000, codecs: "avc1.4d001f,mp4a.40.2", resolution: [640, 286] },
|
|
75
|
+
{ bw: 495894, codecs: "avc1.4d001f,mp4a.40.2", resolution: [480, 214] },
|
|
76
|
+
];
|
|
77
|
+
};
|
|
78
|
+
RefChannelManager.prototype._getAudioTracks = function () {
|
|
79
|
+
return [
|
|
80
|
+
{ language: "en", name: "English", default: true },
|
|
81
|
+
{ language: "es", name: "Spanish", default: false },
|
|
82
|
+
];
|
|
83
|
+
};
|
|
84
|
+
RefChannelManager.prototype._getSubtitleTracks = function () {
|
|
85
|
+
return [
|
|
86
|
+
{ language: "zh", name: "chinese", default: true },
|
|
87
|
+
{ language: "fr", name: "french", default: false }
|
|
88
|
+
];
|
|
89
|
+
};
|
|
90
|
+
return RefChannelManager;
|
|
91
|
+
}());
|
|
92
|
+
var refAssetManager = new RefAssetManager();
|
|
93
|
+
var refChannelManager = new RefChannelManager();
|
|
94
|
+
var engineOptions = {
|
|
95
|
+
heartbeat: "/",
|
|
96
|
+
averageSegmentDuration: 2000,
|
|
97
|
+
channelManager: refChannelManager,
|
|
98
|
+
defaultSlateUri: "https://mtoczko.github.io/hls-test-streams/test-audio-pdt/playlist.m3u8",
|
|
99
|
+
slateRepetitions: 10,
|
|
100
|
+
redisUrl: process.env.REDIS_URL,
|
|
101
|
+
useDemuxedAudio: true,
|
|
102
|
+
alwaysNewSegments: false,
|
|
103
|
+
useVTTSubtitles: true
|
|
104
|
+
};
|
|
105
|
+
var engine = new index_1.ChannelEngine(refAssetManager, engineOptions);
|
|
106
|
+
engine.start();
|
|
107
|
+
engine.listen(process.env.PORT || 8000);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|