eyevinn-channel-engine 4.0.7 → 4.0.8
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/dist/engine/server.d.ts +1 -2
- package/dist/engine/session.js +46 -16
- package/dist/engine/util.d.ts +1 -0
- package/dist/engine/util.js +11 -1
- package/dist/package.json +2 -2
- package/dist/server-demux.js +2 -2
- package/dist/server-multicodec.js +8 -8
- package/engine/server.ts +1 -2
- package/engine/session.js +42 -11
- package/engine/util.js +12 -1
- package/package.json +2 -2
- package/server-demux.ts +2 -2
- package/server-multicodec.ts +9 -9
package/dist/engine/server.d.ts
CHANGED
|
@@ -58,6 +58,7 @@ export interface ChannelProfile {
|
|
|
58
58
|
bw: number;
|
|
59
59
|
codecs: string;
|
|
60
60
|
resolution: number[];
|
|
61
|
+
channels?: string;
|
|
61
62
|
}
|
|
62
63
|
export interface Channel {
|
|
63
64
|
id: string;
|
|
@@ -75,8 +76,6 @@ export interface ClosedCaptions {
|
|
|
75
76
|
export interface AudioTracks {
|
|
76
77
|
language: string;
|
|
77
78
|
name: string;
|
|
78
|
-
channels?: number;
|
|
79
|
-
codecs?: string;
|
|
80
79
|
default?: boolean;
|
|
81
80
|
}
|
|
82
81
|
export interface IChannelManager {
|
package/dist/engine/session.js
CHANGED
|
@@ -43,7 +43,7 @@ var HLSTruncateVod = require('@eyevinn/hls-truncate');
|
|
|
43
43
|
var Readable = require('stream').Readable;
|
|
44
44
|
var SessionState = require('./session_state.js').SessionState;
|
|
45
45
|
var PlayheadState = require('./playhead_state.js').PlayheadState;
|
|
46
|
-
var _a = require('./util.js'), applyFilter = _a.applyFilter, cloudWatchLog = _a.cloudWatchLog, m3u8Header = _a.m3u8Header, logerror = _a.logerror;
|
|
46
|
+
var _a = require('./util.js'), applyFilter = _a.applyFilter, cloudWatchLog = _a.cloudWatchLog, m3u8Header = _a.m3u8Header, logerror = _a.logerror, codecsFromString = _a.codecsFromString;
|
|
47
47
|
var ChaosMonkey = require('./chaos_monkey.js');
|
|
48
48
|
var AVERAGE_SEGMENT_DURATION = 3000;
|
|
49
49
|
var DEFAULT_PLAYHEAD_DIFF_THRESHOLD = 1000;
|
|
@@ -923,7 +923,7 @@ var Session = /** @class */ (function () {
|
|
|
923
923
|
debug("[".concat(this._sessionId, "]: {").concat(mediaSequenceValue, "}_{").concat(currentVod.getLastSequenceMediaSequenceValueAudio(), "} AUDIO"));
|
|
924
924
|
manifestMseq = playheadState.mediaSeqAudio + mediaSequenceValue;
|
|
925
925
|
}
|
|
926
|
-
debug("[".concat(this._sessionId, "]: [").concat(playheadState.vodMediaSeqAudio, "]_[").concat(currentVod.getLiveMediaSequencesCount("audio"), "] AUDIO"));
|
|
926
|
+
debug("[".concat(this._sessionId, "]: [").concat(playheadState.vodMediaSeqAudio, "]_[").concat(currentVod.getLiveMediaSequencesCount("audio"), "] AUDIO (").concat(audioGroupId, ")"));
|
|
927
927
|
m3u8_2 = currentVod.getLiveMediaAudioSequences(playheadState.mediaSeqAudio, audioGroupId, audioLanguage, playheadState.vodMediaSeqAudio, sessionState.discSeqAudio, this.targetDurationPadding, this.forceTargetDuration);
|
|
928
928
|
// # Case: current VOD does not have the selected track.
|
|
929
929
|
if (!m3u8_2) {
|
|
@@ -1346,10 +1346,10 @@ var Session = /** @class */ (function () {
|
|
|
1346
1346
|
};
|
|
1347
1347
|
Session.prototype.getMasterManifestAsync = function (filter) {
|
|
1348
1348
|
return __awaiter(this, void 0, void 0, function () {
|
|
1349
|
-
var m3u8, currentVod, audioGroupIds, defaultAudioGroupId, hasClosedCaptions, i, audioGroupId, j, audioTrack, channels, sessionProfile;
|
|
1349
|
+
var m3u8, currentVod, audioGroupIds, defaultAudioGroupId, hasClosedCaptions, i, audioGroupId, j, audioTrack, _a, _, channels, sessionProfile;
|
|
1350
1350
|
var _this = this;
|
|
1351
|
-
return __generator(this, function (
|
|
1352
|
-
switch (
|
|
1351
|
+
return __generator(this, function (_b) {
|
|
1352
|
+
switch (_b.label) {
|
|
1353
1353
|
case 0:
|
|
1354
1354
|
m3u8 = "#EXTM3U\n";
|
|
1355
1355
|
m3u8 += "#EXT-X-VERSION:4\n";
|
|
@@ -1360,7 +1360,7 @@ var Session = /** @class */ (function () {
|
|
|
1360
1360
|
}
|
|
1361
1361
|
return [4 /*yield*/, this._sessionState.getCurrentVod()];
|
|
1362
1362
|
case 1:
|
|
1363
|
-
currentVod =
|
|
1363
|
+
currentVod = _b.sent();
|
|
1364
1364
|
if (!currentVod) {
|
|
1365
1365
|
throw new Error('Session not ready');
|
|
1366
1366
|
}
|
|
@@ -1378,14 +1378,16 @@ var Session = /** @class */ (function () {
|
|
|
1378
1378
|
audioGroupId = audioGroupIds[i];
|
|
1379
1379
|
for (j = 0; j < this._audioTracks.length; j++) {
|
|
1380
1380
|
audioTrack = this._audioTracks[j];
|
|
1381
|
-
|
|
1381
|
+
_a = currentVod.getAudioCodecsAndChannelsForGroupId(audioGroupId), _ = _a[0], channels = _a[1];
|
|
1382
1382
|
// Make default track if set property is true.
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1383
|
+
m3u8 += "#EXT-X-MEDIA:TYPE=AUDIO" +
|
|
1384
|
+
",GROUP-ID=\"".concat(audioGroupId, "\"") +
|
|
1385
|
+
",LANGUAGE=\"".concat(audioTrack.language, "\"") +
|
|
1386
|
+
",NAME=\"".concat(audioTrack.name, "\"") +
|
|
1387
|
+
",AUTOSELECT=YES,DEFAULT=".concat(audioTrack.default ? 'YES' : 'NO') +
|
|
1388
|
+
",CHANNELS=\"".concat(channels ? channels : 2, "\"") +
|
|
1389
|
+
",URI=\"master-".concat(audioGroupId, "_").concat(audioTrack.language, ".m3u8;session=").concat(this._sessionId, "\"") +
|
|
1390
|
+
"\n";
|
|
1389
1391
|
}
|
|
1390
1392
|
}
|
|
1391
1393
|
// As of now, by default set StreamItem's AUDIO attribute to <first audio group-id>
|
|
@@ -1395,13 +1397,41 @@ var Session = /** @class */ (function () {
|
|
|
1395
1397
|
if (this._sessionProfile) {
|
|
1396
1398
|
sessionProfile = filter ? applyFilter(this._sessionProfile, filter) : this._sessionProfile;
|
|
1397
1399
|
sessionProfile.forEach(function (profile) {
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
+
if (_this.use_demuxed_audio) {
|
|
1401
|
+
// find matching audio group based on codec in stream
|
|
1402
|
+
var audioGroupIdToUse = void 0;
|
|
1403
|
+
var _a = codecsFromString(profile.codecs), _ = _a[0], audioCodec = _a[1];
|
|
1404
|
+
if (audioCodec) {
|
|
1405
|
+
var profileChannels = profile.channels ? profile.channels : "2";
|
|
1406
|
+
audioGroupIdToUse = currentVod.getAudioGroupIdForCodecs(audioCodec, profileChannels);
|
|
1407
|
+
}
|
|
1408
|
+
// skip stream if no corresponding audio group can be found
|
|
1409
|
+
if (audioGroupIdToUse) {
|
|
1410
|
+
m3u8 += '#EXT-X-STREAM-INF:BANDWIDTH=' + profile.bw +
|
|
1411
|
+
',RESOLUTION=' + profile.resolution[0] + 'x' + profile.resolution[1] +
|
|
1412
|
+
',CODECS="' + profile.codecs + '"' +
|
|
1413
|
+
",AUDIO=\"".concat(audioGroupIdToUse, "\"") +
|
|
1414
|
+
(hasClosedCaptions ? ',CLOSED-CAPTIONS="cc"' : '') + '\n';
|
|
1415
|
+
m3u8 += "master" + profile.bw + ".m3u8;session=" + _this._sessionId + "\n";
|
|
1416
|
+
}
|
|
1417
|
+
}
|
|
1418
|
+
else {
|
|
1419
|
+
m3u8 += '#EXT-X-STREAM-INF:BANDWIDTH=' + profile.bw +
|
|
1420
|
+
',RESOLUTION=' + profile.resolution[0] + 'x' + profile.resolution[1] +
|
|
1421
|
+
',CODECS="' + profile.codecs + '"' +
|
|
1422
|
+
(defaultAudioGroupId ? ",AUDIO=\"".concat(defaultAudioGroupId, "\"") : '') +
|
|
1423
|
+
(hasClosedCaptions ? ',CLOSED-CAPTIONS="cc"' : '') + '\n';
|
|
1424
|
+
m3u8 += "master" + profile.bw + ".m3u8;session=" + _this._sessionId + "\n";
|
|
1425
|
+
}
|
|
1400
1426
|
});
|
|
1401
1427
|
}
|
|
1402
1428
|
else {
|
|
1403
1429
|
currentVod.getUsageProfiles().forEach(function (profile) {
|
|
1404
|
-
m3u8 += '#EXT-X-STREAM-INF:BANDWIDTH=' + profile.bw +
|
|
1430
|
+
m3u8 += '#EXT-X-STREAM-INF:BANDWIDTH=' + profile.bw +
|
|
1431
|
+
',RESOLUTION=' + profile.resolution +
|
|
1432
|
+
',CODECS="' + profile.codecs + '"' +
|
|
1433
|
+
(defaultAudioGroupId ? ",AUDIO=\"".concat(defaultAudioGroupId, "\"") : '') +
|
|
1434
|
+
(hasClosedCaptions ? ',CLOSED-CAPTIONS="cc"' : '') + '\n';
|
|
1405
1435
|
m3u8 += "master" + profile.bw + ".m3u8;session=" + _this._sessionId + "\n";
|
|
1406
1436
|
});
|
|
1407
1437
|
}
|
package/dist/engine/util.d.ts
CHANGED
|
@@ -17,3 +17,4 @@ export class WaitTimeGenerator {
|
|
|
17
17
|
export function findNearestValue(val: any, array: any): any;
|
|
18
18
|
export function isValidUrl(url: any): boolean;
|
|
19
19
|
export function fetchWithRetry(uri: any, opts: any, maxRetries: any, retryDelayMs: any, timeoutMs: any, debug: any): Promise<any>;
|
|
20
|
+
export function codecsFromString(codecs: any): any[];
|
package/dist/engine/util.js
CHANGED
|
@@ -266,6 +266,15 @@ var fetchWithRetry = function (uri, opts, maxRetries, retryDelayMs, timeoutMs, d
|
|
|
266
266
|
}
|
|
267
267
|
});
|
|
268
268
|
}); };
|
|
269
|
+
var codecsFromString = function (codecs) {
|
|
270
|
+
var audioCodecs = codecs.split(",").find(function (c) {
|
|
271
|
+
return c.match(/^mp4a/) || c.match(/^ac-3/) || c.match(/^ec-3/);
|
|
272
|
+
});
|
|
273
|
+
var videoCodecs = codecs.split(",").find(function (c) {
|
|
274
|
+
return c.match(/^avc/) || c.match(/^hevc/) || c.match(/^dvh/);
|
|
275
|
+
});
|
|
276
|
+
return [videoCodecs, audioCodecs];
|
|
277
|
+
};
|
|
269
278
|
module.exports = {
|
|
270
279
|
filterQueryParser: filterQueryParser,
|
|
271
280
|
applyFilter: applyFilter,
|
|
@@ -277,5 +286,6 @@ module.exports = {
|
|
|
277
286
|
WaitTimeGenerator: WaitTimeGenerator,
|
|
278
287
|
findNearestValue: findNearestValue,
|
|
279
288
|
isValidUrl: isValidUrl,
|
|
280
|
-
fetchWithRetry: fetchWithRetry
|
|
289
|
+
fetchWithRetry: fetchWithRetry,
|
|
290
|
+
codecsFromString: codecsFromString
|
|
281
291
|
};
|
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.8",
|
|
4
4
|
"description": "OTT TV Channel Engine",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"dependencies": {
|
|
27
27
|
"@eyevinn/hls-repeat": "^0.2.0",
|
|
28
28
|
"@eyevinn/hls-truncate": "^0.2.0",
|
|
29
|
-
"@eyevinn/hls-vodtolive": "^2.
|
|
29
|
+
"@eyevinn/hls-vodtolive": "^2.3.3",
|
|
30
30
|
"@eyevinn/m3u8": "^0.5.3",
|
|
31
31
|
"abort-controller": "^3.0.0",
|
|
32
32
|
"debug": "^3.2.7",
|
package/dist/server-demux.js
CHANGED
|
@@ -81,8 +81,8 @@ var RefChannelManager = /** @class */ (function () {
|
|
|
81
81
|
};
|
|
82
82
|
RefChannelManager.prototype._getAudioTracks = function () {
|
|
83
83
|
return [
|
|
84
|
-
{ language: "en", name: "English" },
|
|
85
|
-
{ language: "sp", name: "Spanish" }
|
|
84
|
+
{ language: "en", name: "English", default: true },
|
|
85
|
+
{ language: "sp", name: "Spanish", default: false }
|
|
86
86
|
];
|
|
87
87
|
};
|
|
88
88
|
return RefChannelManager;
|
|
@@ -65,18 +65,18 @@ var RefChannelManager = /** @class */ (function () {
|
|
|
65
65
|
};
|
|
66
66
|
RefChannelManager.prototype._getProfile = function () {
|
|
67
67
|
return [
|
|
68
|
-
{ resolution: [640, 360], bw: 3663471, codecs: "avc1.64001F,mp4a.40.2" },
|
|
69
|
-
{ resolution: [1280, 720], bw: 5841380, codecs: "avc1.64001F,mp4a.40.2" },
|
|
70
|
-
{ resolution: [1920, 1080], bw: 8973571, codecs: "avc1.64001F,mp4a.40.2" },
|
|
71
|
-
{ resolution: [640, 360], bw: 4301519, codecs: "avc1.64001F,ec-3" },
|
|
72
|
-
{ resolution: [1280, 720], bw: 6479428, codecs: "avc1.64001F,ec-3" },
|
|
73
|
-
{ resolution: [1920, 1080], bw: 9611619, codecs: "avc1.640032,ec-3" },
|
|
68
|
+
{ resolution: [640, 360], bw: 3663471, codecs: "avc1.64001F,mp4a.40.2", channels: "2" },
|
|
69
|
+
{ resolution: [1280, 720], bw: 5841380, codecs: "avc1.64001F,mp4a.40.2", channels: "2" },
|
|
70
|
+
{ resolution: [1920, 1080], bw: 8973571, codecs: "avc1.64001F,mp4a.40.2", channels: "2" },
|
|
71
|
+
{ resolution: [640, 360], bw: 4301519, codecs: "avc1.64001F,ec-3", channels: "16/JOC" },
|
|
72
|
+
{ resolution: [1280, 720], bw: 6479428, codecs: "avc1.64001F,ec-3", channels: "16/JOC" },
|
|
73
|
+
{ resolution: [1920, 1080], bw: 9611619, codecs: "avc1.640032,ec-3", channels: "16/JOC" },
|
|
74
74
|
];
|
|
75
75
|
};
|
|
76
76
|
RefChannelManager.prototype._getAudioTracks = function () {
|
|
77
77
|
return [
|
|
78
|
-
{ language: "ja", "name": "日本語
|
|
79
|
-
{ language: "
|
|
78
|
+
{ language: "ja", "name": "日本語", default: true },
|
|
79
|
+
{ language: "en", "name": "English", default: false }
|
|
80
80
|
];
|
|
81
81
|
};
|
|
82
82
|
return RefChannelManager;
|
package/engine/server.ts
CHANGED
|
@@ -99,6 +99,7 @@ export interface ChannelProfile {
|
|
|
99
99
|
bw: number;
|
|
100
100
|
codecs: string;
|
|
101
101
|
resolution: number[];
|
|
102
|
+
channels?: string;
|
|
102
103
|
}
|
|
103
104
|
|
|
104
105
|
export interface Channel {
|
|
@@ -119,8 +120,6 @@ export interface ClosedCaptions {
|
|
|
119
120
|
export interface AudioTracks {
|
|
120
121
|
language: string;
|
|
121
122
|
name: string;
|
|
122
|
-
channels?: number;
|
|
123
|
-
codecs?: string;
|
|
124
123
|
default?: boolean;
|
|
125
124
|
}
|
|
126
125
|
|
package/engine/session.js
CHANGED
|
@@ -9,7 +9,7 @@ const Readable = require('stream').Readable;
|
|
|
9
9
|
const { SessionState } = require('./session_state.js');
|
|
10
10
|
const { PlayheadState } = require('./playhead_state.js');
|
|
11
11
|
|
|
12
|
-
const { applyFilter, cloudWatchLog, m3u8Header, logerror } = require('./util.js');
|
|
12
|
+
const { applyFilter, cloudWatchLog, m3u8Header, logerror, codecsFromString } = require('./util.js');
|
|
13
13
|
const ChaosMonkey = require('./chaos_monkey.js');
|
|
14
14
|
|
|
15
15
|
const AVERAGE_SEGMENT_DURATION = 3000;
|
|
@@ -655,7 +655,7 @@ class Session {
|
|
|
655
655
|
debug(`[${this._sessionId}]: {${mediaSequenceValue}}_{${currentVod.getLastSequenceMediaSequenceValueAudio()}} AUDIO`);
|
|
656
656
|
manifestMseq = playheadState.mediaSeqAudio + mediaSequenceValue;
|
|
657
657
|
}
|
|
658
|
-
debug(`[${this._sessionId}]: [${playheadState.vodMediaSeqAudio}]_[${currentVod.getLiveMediaSequencesCount("audio")}] AUDIO`);
|
|
658
|
+
debug(`[${this._sessionId}]: [${playheadState.vodMediaSeqAudio}]_[${currentVod.getLiveMediaSequencesCount("audio")}] AUDIO (${audioGroupId})`);
|
|
659
659
|
const m3u8 = currentVod.getLiveMediaAudioSequences(
|
|
660
660
|
playheadState.mediaSeqAudio,
|
|
661
661
|
audioGroupId,
|
|
@@ -959,13 +959,16 @@ class Session {
|
|
|
959
959
|
let audioGroupId = audioGroupIds[i];
|
|
960
960
|
for (let j = 0; j < this._audioTracks.length; j++) {
|
|
961
961
|
let audioTrack = this._audioTracks[j];
|
|
962
|
-
|
|
962
|
+
const [_, channels] = currentVod.getAudioCodecsAndChannelsForGroupId(audioGroupId);
|
|
963
963
|
// Make default track if set property is true.
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
964
|
+
m3u8 += `#EXT-X-MEDIA:TYPE=AUDIO` +
|
|
965
|
+
`,GROUP-ID="${audioGroupId}"` +
|
|
966
|
+
`,LANGUAGE="${audioTrack.language}"` +
|
|
967
|
+
`,NAME="${audioTrack.name}"` +
|
|
968
|
+
`,AUTOSELECT=YES,DEFAULT=${audioTrack.default ? 'YES' : 'NO'}` +
|
|
969
|
+
`,CHANNELS="${channels ? channels : 2}"` +
|
|
970
|
+
`,URI="master-${audioGroupId}_${audioTrack.language}.m3u8;session=${this._sessionId}"` +
|
|
971
|
+
"\n";
|
|
969
972
|
}
|
|
970
973
|
}
|
|
971
974
|
// As of now, by default set StreamItem's AUDIO attribute to <first audio group-id>
|
|
@@ -975,12 +978,40 @@ class Session {
|
|
|
975
978
|
if (this._sessionProfile) {
|
|
976
979
|
const sessionProfile = filter ? applyFilter(this._sessionProfile, filter) : this._sessionProfile;
|
|
977
980
|
sessionProfile.forEach(profile => {
|
|
978
|
-
|
|
979
|
-
|
|
981
|
+
if (this.use_demuxed_audio) {
|
|
982
|
+
// find matching audio group based on codec in stream
|
|
983
|
+
let audioGroupIdToUse;
|
|
984
|
+
const [_, audioCodec] = codecsFromString(profile.codecs);
|
|
985
|
+
if (audioCodec) {
|
|
986
|
+
const profileChannels = profile.channels ? profile.channels : "2";
|
|
987
|
+
audioGroupIdToUse = currentVod.getAudioGroupIdForCodecs(audioCodec, profileChannels);
|
|
988
|
+
}
|
|
989
|
+
|
|
990
|
+
// skip stream if no corresponding audio group can be found
|
|
991
|
+
if (audioGroupIdToUse) {
|
|
992
|
+
m3u8 += '#EXT-X-STREAM-INF:BANDWIDTH=' + profile.bw +
|
|
993
|
+
',RESOLUTION=' + profile.resolution[0] + 'x' + profile.resolution[1] +
|
|
994
|
+
',CODECS="' + profile.codecs + '"' +
|
|
995
|
+
`,AUDIO="${audioGroupIdToUse}"` +
|
|
996
|
+
(hasClosedCaptions ? ',CLOSED-CAPTIONS="cc"' : '') + '\n';
|
|
997
|
+
m3u8 += "master" + profile.bw + ".m3u8;session=" + this._sessionId + "\n";
|
|
998
|
+
}
|
|
999
|
+
} else {
|
|
1000
|
+
m3u8 += '#EXT-X-STREAM-INF:BANDWIDTH=' + profile.bw +
|
|
1001
|
+
',RESOLUTION=' + profile.resolution[0] + 'x' + profile.resolution[1] +
|
|
1002
|
+
',CODECS="' + profile.codecs + '"' +
|
|
1003
|
+
(defaultAudioGroupId ? `,AUDIO="${defaultAudioGroupId}"` : '') +
|
|
1004
|
+
(hasClosedCaptions ? ',CLOSED-CAPTIONS="cc"' : '') + '\n';
|
|
1005
|
+
m3u8 += "master" + profile.bw + ".m3u8;session=" + this._sessionId + "\n";
|
|
1006
|
+
}
|
|
980
1007
|
});
|
|
981
1008
|
} else {
|
|
982
1009
|
currentVod.getUsageProfiles().forEach(profile => {
|
|
983
|
-
m3u8 += '#EXT-X-STREAM-INF:BANDWIDTH=' + profile.bw +
|
|
1010
|
+
m3u8 += '#EXT-X-STREAM-INF:BANDWIDTH=' + profile.bw +
|
|
1011
|
+
',RESOLUTION=' + profile.resolution +
|
|
1012
|
+
',CODECS="' + profile.codecs + '"' +
|
|
1013
|
+
(defaultAudioGroupId ? `,AUDIO="${defaultAudioGroupId}"` : '') +
|
|
1014
|
+
(hasClosedCaptions ? ',CLOSED-CAPTIONS="cc"' : '') + '\n';
|
|
984
1015
|
m3u8 += "master" + profile.bw + ".m3u8;session=" + this._sessionId + "\n";
|
|
985
1016
|
});
|
|
986
1017
|
}
|
package/engine/util.js
CHANGED
|
@@ -214,6 +214,16 @@ const fetchWithRetry = async (uri, opts, maxRetries, retryDelayMs, timeoutMs, de
|
|
|
214
214
|
}
|
|
215
215
|
};
|
|
216
216
|
|
|
217
|
+
const codecsFromString = (codecs) => {
|
|
218
|
+
const audioCodecs = codecs.split(",").find(c => {
|
|
219
|
+
return c.match(/^mp4a/) || c.match(/^ac-3/) || c.match(/^ec-3/);
|
|
220
|
+
});
|
|
221
|
+
const videoCodecs = codecs.split(",").find(c => {
|
|
222
|
+
return c.match(/^avc/) || c.match(/^hevc/) || c.match(/^dvh/);
|
|
223
|
+
});
|
|
224
|
+
return [videoCodecs, audioCodecs];
|
|
225
|
+
};
|
|
226
|
+
|
|
217
227
|
module.exports = {
|
|
218
228
|
filterQueryParser,
|
|
219
229
|
applyFilter,
|
|
@@ -225,5 +235,6 @@ module.exports = {
|
|
|
225
235
|
WaitTimeGenerator,
|
|
226
236
|
findNearestValue,
|
|
227
237
|
isValidUrl,
|
|
228
|
-
fetchWithRetry
|
|
238
|
+
fetchWithRetry,
|
|
239
|
+
codecsFromString
|
|
229
240
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eyevinn-channel-engine",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.8",
|
|
4
4
|
"description": "OTT TV Channel Engine",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"dependencies": {
|
|
27
27
|
"@eyevinn/hls-repeat": "^0.2.0",
|
|
28
28
|
"@eyevinn/hls-truncate": "^0.2.0",
|
|
29
|
-
"@eyevinn/hls-vodtolive": "^2.
|
|
29
|
+
"@eyevinn/hls-vodtolive": "^2.3.3",
|
|
30
30
|
"@eyevinn/m3u8": "^0.5.3",
|
|
31
31
|
"abort-controller": "^3.0.0",
|
|
32
32
|
"debug": "^3.2.7",
|
package/server-demux.ts
CHANGED
|
@@ -91,8 +91,8 @@ class RefChannelManager implements IChannelManager {
|
|
|
91
91
|
}
|
|
92
92
|
_getAudioTracks(): AudioTracks[] {
|
|
93
93
|
return [
|
|
94
|
-
{ language: "en", name: "English" },
|
|
95
|
-
{ language: "sp", name: "Spanish" }
|
|
94
|
+
{ language: "en", name: "English", default: true },
|
|
95
|
+
{ language: "sp", name: "Spanish", default: false }
|
|
96
96
|
];
|
|
97
97
|
}
|
|
98
98
|
}
|
package/server-multicodec.ts
CHANGED
|
@@ -69,20 +69,20 @@ class RefChannelManager implements IChannelManager {
|
|
|
69
69
|
|
|
70
70
|
_getProfile(): ChannelProfile[] {
|
|
71
71
|
return [
|
|
72
|
-
{ resolution: [640, 360], bw: 3663471, codecs: "avc1.64001F,mp4a.40.2" },
|
|
73
|
-
{ resolution: [1280, 720], bw: 5841380, codecs: "avc1.64001F,mp4a.40.2" },
|
|
74
|
-
{ resolution: [1920, 1080], bw: 8973571, codecs: "avc1.64001F,mp4a.40.2" },
|
|
72
|
+
{ resolution: [640, 360], bw: 3663471, codecs: "avc1.64001F,mp4a.40.2", channels: "2" },
|
|
73
|
+
{ resolution: [1280, 720], bw: 5841380, codecs: "avc1.64001F,mp4a.40.2", channels: "2" },
|
|
74
|
+
{ resolution: [1920, 1080], bw: 8973571, codecs: "avc1.64001F,mp4a.40.2", channels: "2" },
|
|
75
75
|
|
|
76
|
-
{ resolution: [640, 360], bw: 4301519, codecs: "avc1.64001F,ec-3" },
|
|
77
|
-
{ resolution: [1280, 720], bw: 6479428, codecs: "avc1.64001F,ec-3" },
|
|
78
|
-
{ resolution: [1920, 1080], bw: 9611619, codecs: "avc1.640032,ec-3" },
|
|
76
|
+
{ resolution: [640, 360], bw: 4301519, codecs: "avc1.64001F,ec-3", channels: "16/JOC" },
|
|
77
|
+
{ resolution: [1280, 720], bw: 6479428, codecs: "avc1.64001F,ec-3", channels: "16/JOC" },
|
|
78
|
+
{ resolution: [1920, 1080], bw: 9611619, codecs: "avc1.640032,ec-3", channels: "16/JOC" },
|
|
79
79
|
];
|
|
80
80
|
}
|
|
81
81
|
|
|
82
82
|
_getAudioTracks(): AudioTracks[] {
|
|
83
83
|
return [
|
|
84
|
-
{ language: "ja", "name": "日本語
|
|
85
|
-
{ language: "
|
|
84
|
+
{ language: "ja", "name": "日本語", default: true },
|
|
85
|
+
{ language: "en", "name": "English", default: false }
|
|
86
86
|
];
|
|
87
87
|
}
|
|
88
88
|
}
|
|
@@ -101,4 +101,4 @@ const engineOptions: ChannelEngineOpts = {
|
|
|
101
101
|
|
|
102
102
|
const engine = new ChannelEngine(refAssetManager, engineOptions);
|
|
103
103
|
engine.start();
|
|
104
|
-
engine.listen(process.env.PORT || 8000);
|
|
104
|
+
engine.listen(process.env.PORT || 8000);
|