eyevinn-channel-engine 4.0.10 → 4.0.12
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/README.md +11 -0
- package/dist/engine/redis_state_store.js +2 -2
- package/dist/engine/session.js +5 -0
- package/dist/package.json +2 -2
- package/engine/redis_state_store.js +2 -2
- package/engine/session.js +7 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -17,6 +17,7 @@ A live demo and example is available here: [https://vod2live.eyevinn.technology]
|
|
|
17
17
|
- Produce a personalized 24/7 HLS live channel unique for each viewer
|
|
18
18
|
- Mix VOD2Live channel with a "real" live HLS stream
|
|
19
19
|
- Develop adapters to plugin with custom scheduling endpoints
|
|
20
|
+
- High Availability with Redis Cache as shared state store
|
|
20
21
|
- And much more!
|
|
21
22
|
|
|
22
23
|
## System Requirements
|
|
@@ -38,6 +39,16 @@ Supported Node.js Versions
|
|
|
38
39
|
|
|
39
40
|
*\* not supported with demuxed sources*
|
|
40
41
|
|
|
42
|
+
## High Availability Support
|
|
43
|
+
|
|
44
|
+
[High availability support](https://vod2live.docs.eyevinn.technology/usage-guide.html#high-availability) is from v3 general available in the Channel Engine and it uses Redis as the shared storage. This allows you to run a replicaset behind a round-robin load balancer. Supported Redis Engine versions:
|
|
45
|
+
|
|
46
|
+
| Version | Supported |
|
|
47
|
+
| ------- | --------- |
|
|
48
|
+
| 5.x | Yes |
|
|
49
|
+
| 6.x | Yes |
|
|
50
|
+
| 7.x | No |
|
|
51
|
+
|
|
41
52
|
## Usage
|
|
42
53
|
|
|
43
54
|
Follow [this tutorial](https://vod2live.docs.eyevinn.technology/getting-started.html) to get started building your own FAST channel engine.
|
|
@@ -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 createClient = require("redis").createClient;
|
|
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 = createClient(opts.redisUrl);
|
|
54
54
|
}
|
|
55
55
|
RedisStateStore.prototype.initAsync = function (id, initData) {
|
|
56
56
|
return __awaiter(this, void 0, void 0, function () {
|
package/dist/engine/session.js
CHANGED
|
@@ -1373,6 +1373,7 @@ var Session = /** @class */ (function () {
|
|
|
1373
1373
|
throw new Error('Session not ready');
|
|
1374
1374
|
}
|
|
1375
1375
|
audioGroupIds = currentVod.getAudioGroups();
|
|
1376
|
+
debug("[".concat(this._sessionId, "]: currentVod.getAudioGroups()=").concat(audioGroupIds.join(",")));
|
|
1376
1377
|
hasClosedCaptions = this._closedCaptions && this._closedCaptions.length > 0;
|
|
1377
1378
|
if (hasClosedCaptions) {
|
|
1378
1379
|
this._closedCaptions.forEach(function (cc) {
|
|
@@ -1412,7 +1413,11 @@ var Session = /** @class */ (function () {
|
|
|
1412
1413
|
if (audioCodec) {
|
|
1413
1414
|
var profileChannels = profile.channels ? profile.channels : "2";
|
|
1414
1415
|
audioGroupIdToUse = currentVod.getAudioGroupIdForCodecs(audioCodec, profileChannels);
|
|
1416
|
+
if (!audioGroupIds.includes(audioGroupIdToUse)) {
|
|
1417
|
+
audioGroupIdToUse = defaultAudioGroupId;
|
|
1418
|
+
}
|
|
1415
1419
|
}
|
|
1420
|
+
debug("[".concat(_this._sessionId, "]: audioGroupIdToUse=").concat(audioGroupIdToUse));
|
|
1416
1421
|
// skip stream if no corresponding audio group can be found
|
|
1417
1422
|
if (audioGroupIdToUse) {
|
|
1418
1423
|
m3u8 += '#EXT-X-STREAM-INF:BANDWIDTH=' + profile.bw +
|
package/dist/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eyevinn-channel-engine",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.12",
|
|
4
4
|
"description": "OTT TV Channel Engine",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"nock": "^13.1.1",
|
|
35
35
|
"node-fetch": "^2.6.1",
|
|
36
36
|
"promise.allsettled": "^1.0.4",
|
|
37
|
-
"redis": "
|
|
37
|
+
"redis": "3.1.0",
|
|
38
38
|
"request": ">=2.88.0",
|
|
39
39
|
"restify": "9.0.0",
|
|
40
40
|
"restify-errors": "^8.0.2",
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const
|
|
1
|
+
const { createClient } = require("redis");
|
|
2
2
|
const debug = require("debug")("redis-state-store");
|
|
3
3
|
|
|
4
4
|
const DEFAULT_VOLATILE_KEY_TTL = 5; // Timeout so it should not expire within one normal increment iteration (in seconds)
|
|
@@ -16,7 +16,7 @@ class RedisStateStore {
|
|
|
16
16
|
debug(`Overriding default, volatileKeyTTL=${opts.volatileKeyTTL}s`);
|
|
17
17
|
this.volatileKeyTTL = opts.volatileKeyTTL;
|
|
18
18
|
}
|
|
19
|
-
this.client =
|
|
19
|
+
this.client = createClient(opts.redisUrl);
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
async initAsync(id, initData) {
|
package/engine/session.js
CHANGED
|
@@ -951,6 +951,7 @@ class Session {
|
|
|
951
951
|
throw new Error('Session not ready');
|
|
952
952
|
}
|
|
953
953
|
let audioGroupIds = currentVod.getAudioGroups();
|
|
954
|
+
debug(`[${this._sessionId}]: currentVod.getAudioGroups()=${audioGroupIds.join(",")}`);
|
|
954
955
|
let defaultAudioGroupId;
|
|
955
956
|
let hasClosedCaptions = this._closedCaptions && this._closedCaptions.length > 0;
|
|
956
957
|
if (hasClosedCaptions) {
|
|
@@ -987,12 +988,17 @@ class Session {
|
|
|
987
988
|
if (this.use_demuxed_audio) {
|
|
988
989
|
// find matching audio group based on codec in stream
|
|
989
990
|
let audioGroupIdToUse;
|
|
990
|
-
const [_, audioCodec] = codecsFromString(profile.codecs);
|
|
991
|
+
const [_, audioCodec] = codecsFromString(profile.codecs);
|
|
991
992
|
if (audioCodec) {
|
|
992
993
|
const profileChannels = profile.channels ? profile.channels : "2";
|
|
993
994
|
audioGroupIdToUse = currentVod.getAudioGroupIdForCodecs(audioCodec, profileChannels);
|
|
995
|
+
if (!audioGroupIds.includes(audioGroupIdToUse)) {
|
|
996
|
+
audioGroupIdToUse = defaultAudioGroupId;
|
|
997
|
+
}
|
|
994
998
|
}
|
|
995
999
|
|
|
1000
|
+
debug(`[${this._sessionId}]: audioGroupIdToUse=${audioGroupIdToUse}`);
|
|
1001
|
+
|
|
996
1002
|
// skip stream if no corresponding audio group can be found
|
|
997
1003
|
if (audioGroupIdToUse) {
|
|
998
1004
|
m3u8 += '#EXT-X-STREAM-INF:BANDWIDTH=' + profile.bw +
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eyevinn-channel-engine",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.12",
|
|
4
4
|
"description": "OTT TV Channel Engine",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"nock": "^13.1.1",
|
|
35
35
|
"node-fetch": "^2.6.1",
|
|
36
36
|
"promise.allsettled": "^1.0.4",
|
|
37
|
-
"redis": "
|
|
37
|
+
"redis": "3.1.0",
|
|
38
38
|
"request": ">=2.88.0",
|
|
39
39
|
"restify": "9.0.0",
|
|
40
40
|
"restify-errors": "^8.0.2",
|