eyevinn-channel-engine 5.1.3 → 5.2.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/.github/workflows/nodejs.yml +1 -1
- package/.github/workflows/publish.yml +1 -1
- package/.github/workflows/rc.yml +1 -1
- package/CONTRIBUTING.md +40 -0
- package/Dockerfile +1 -1
- package/README.md +70 -8
- package/dist/engine/chaos_monkey.d.ts +1 -1
- package/dist/engine/chaos_monkey.js +1 -0
- package/dist/engine/event_stream.d.ts +1 -6
- package/dist/engine/event_stream.js +2 -0
- package/dist/engine/memcached_state_store.d.ts +1 -13
- package/dist/engine/memcached_state_store.js +4 -0
- package/dist/engine/memory_state_store.d.ts +1 -13
- package/dist/engine/memory_state_store.js +5 -0
- package/dist/engine/playhead_state.d.ts +0 -26
- package/dist/engine/playhead_state.js +9 -0
- package/dist/engine/preflight.d.ts +1 -1
- package/dist/engine/preflight.js +1 -0
- package/dist/engine/redis_state_store.d.ts +1 -19
- package/dist/engine/redis_state_store.js +5 -0
- package/dist/engine/server.d.ts +27 -0
- package/dist/engine/server.js +140 -6
- package/dist/engine/session.d.ts +1 -148
- package/dist/engine/session.js +380 -6
- package/dist/engine/session_live.d.ts +1 -181
- package/dist/engine/session_live.js +19 -4
- package/dist/engine/session_live_state.d.ts +0 -23
- package/dist/engine/session_live_state.js +5 -0
- package/dist/engine/session_state.d.ts +0 -45
- package/dist/engine/session_state.js +10 -0
- package/dist/engine/shared_state_store.d.ts +1 -25
- package/dist/engine/shared_state_store.js +10 -0
- package/dist/engine/state_store_types.d.ts +32 -0
- package/dist/engine/state_store_types.js +5 -0
- package/dist/engine/stream_switcher.d.ts +1 -40
- package/dist/engine/stream_switcher.js +108 -20
- package/dist/engine/subtitle_slicer.d.ts +1 -8
- package/dist/engine/subtitle_slicer.js +1 -0
- package/dist/engine/util.d.ts +1 -29
- package/dist/engine/util.js +2 -1
- package/dist/examples/adbreak.d.ts +1 -0
- package/dist/examples/adbreak.js +104 -0
- package/dist/index.d.ts +1 -1
- package/dist/package.json +20 -4
- package/docs/design/mixing-muxed-demuxed-audio.md +153 -0
- package/docs/design/subtitles-live-mix-demux.md +135 -0
- package/docs/reference.md +67 -0
- package/engine/chaos_monkey.ts +17 -0
- package/engine/{event_stream.js → event_stream.ts} +5 -3
- package/engine/{memcached_state_store.js → memcached_state_store.ts} +19 -12
- package/engine/memory_state_store.ts +71 -0
- package/engine/{playhead_state.js → playhead_state.ts} +92 -82
- package/engine/{preflight.js → preflight.ts} +1 -1
- package/engine/{redis_state_store.js → redis_state_store.ts} +216 -208
- package/engine/server.ts +210 -8
- package/engine/{session.js → session.ts} +404 -18
- package/engine/{session_live.js → session_live.ts} +54 -31
- package/engine/{session_live_state.js → session_live_state.ts} +129 -120
- package/engine/{session_state.js → session_state.ts} +269 -248
- package/engine/{shared_state_store.js → shared_state_store.ts} +31 -19
- package/engine/state_store_types.ts +35 -0
- package/engine/{stream_switcher.js → stream_switcher.ts} +133 -34
- package/engine/{subtitle_slicer.js → subtitle_slicer.ts} +10 -8
- package/engine/{util.js → util.ts} +28 -24
- package/examples/adbreak.ts +115 -0
- package/index.ts +2 -0
- package/package.json +20 -4
- package/spec/engine/custom_vod_request_params_spec.ts +99 -0
- package/spec/engine/drm_spec.ts +128 -0
- package/spec/engine/{engine_spec.js → engine_spec.ts} +44 -1
- package/spec/engine/{ha_spec.js → ha_spec.ts} +7 -4
- package/spec/engine/{init_switching_spec.js → init_switching_spec.ts} +10 -6
- package/spec/engine/{interface_spec.js → interface_spec.ts} +16 -4
- package/spec/engine/{playhead_live_spec.js → playhead_live_spec.ts} +2 -1
- package/spec/engine/{playhead_spec.js → playhead_spec.ts} +15 -8
- package/spec/engine/session_spec.ts +800 -0
- package/spec/engine/stream_switcher_audio_reconcile_spec.ts +158 -0
- package/spec/engine/{stream_switcher_spec.js → stream_switcher_spec.ts} +111 -13
- package/spec/engine/subtitle_missing_language_spec.ts +196 -0
- package/spec/engine/{subtitle_spec.js → subtitle_spec.ts} +28 -27
- package/spec/helpers/ts-resolve.js +65 -0
- package/spec/support/jasmine.json +1 -1
- package/spec/testvectors/hls_subs_no_language/config.subtitleTracks.json +12 -0
- package/spec/testvectors/hls_subs_no_language/evidence_dummy_segments_name_mismatch.m3u8 +24 -0
- package/spec/testvectors/hls_subs_no_language/evidence_real_cues_name_match.m3u8 +24 -0
- package/spec/testvectors/hls_subs_no_language/french.m3u8 +9 -0
- package/spec/testvectors/hls_subs_no_language/master.m3u8 +11 -0
- package/spec/testvectors/hls_subs_no_language/video.m3u8 +25 -0
- package/spec/testvectors/slate/master.m3u8 +3 -0
- package/spec/testvectors/slate/media.m3u8 +9 -0
- package/tsconfig.json +21 -4
- package/tsconfig.spec.json +16 -0
- package/engine/chaos_monkey.js +0 -17
- package/engine/memory_state_store.js +0 -63
- package/spec/engine/session_spec.js +0 -116
- /package/spec/engine/{session_live_spec.js → session_live_spec.ts} +0 -0
- /package/spec/engine/{util_spec.js → util_spec.ts} +0 -0
package/.github/workflows/rc.yml
CHANGED
package/CONTRIBUTING.md
CHANGED
|
@@ -17,6 +17,46 @@ We follow the [GitHub Flow](https://guides.github.com/introduction/flow/index.ht
|
|
|
17
17
|
|
|
18
18
|
When submitting code changes your submissions are understood to be under the same MIT License that covers the project. Feel free to contact Eyevinn Technology if that's a concern.
|
|
19
19
|
|
|
20
|
+
# TypeScript migration
|
|
21
|
+
|
|
22
|
+
The `engine/` tree is being migrated from JavaScript to TypeScript **incrementally**, one
|
|
23
|
+
module at a time, so that `master` keeps building and testing green throughout. The build
|
|
24
|
+
(`npm run build`, which runs `tsc --project ./`) already compiles a mixed JS/TS tree because
|
|
25
|
+
`allowJs` is enabled in `tsconfig.json`.
|
|
26
|
+
|
|
27
|
+
## Target strictness level
|
|
28
|
+
|
|
29
|
+
The end state is a fully-typed, strictly-checked tree:
|
|
30
|
+
|
|
31
|
+
- `strict: true` (implies `noImplicitAny`, `strictNullChecks`, etc.)
|
|
32
|
+
- `checkJs: true` for any remaining `.js` files
|
|
33
|
+
|
|
34
|
+
These global flags are **intentionally not enabled yet**. Turning them on across the ~7,500
|
|
35
|
+
LOC of currently-untyped JS would surface a large number of errors at once and break
|
|
36
|
+
`master`'s build. Instead, opt in **per file** as each module is hardened:
|
|
37
|
+
|
|
38
|
+
- Add `// @ts-check` at the top of a `.js` file to type-check just that file, or
|
|
39
|
+
- Convert the file to `.ts` (preferred — see checklist below).
|
|
40
|
+
|
|
41
|
+
The global `strict` / `checkJs` flags land **last**, in the final migration slice (**#376**),
|
|
42
|
+
once every module has already been converted or individually `@ts-check`-clean.
|
|
43
|
+
|
|
44
|
+
## Per-file conversion checklist
|
|
45
|
+
|
|
46
|
+
Convert **one module per commit** to keep diffs reviewable and bisectable:
|
|
47
|
+
|
|
48
|
+
1. Rename the file `.js` → `.ts` (use `git mv` to preserve history).
|
|
49
|
+
2. Add explicit types for all exported functions, classes, and their public members.
|
|
50
|
+
3. Keep the **public API and runtime behavior identical** — this is a type-only migration,
|
|
51
|
+
no behavior changes. Prefer `unknown` + narrowing over `any` where practical; leave a
|
|
52
|
+
`// TODO(ts):` note if a proper type is deferred.
|
|
53
|
+
4. Run `npm run build && npm test` locally and confirm both are green (the jasmine suite must
|
|
54
|
+
report `0 failures`).
|
|
55
|
+
5. Commit with a conventional-commit message, e.g. `refactor(engine): migrate util to TypeScript`.
|
|
56
|
+
|
|
57
|
+
CI already gates every push on `npm run build` (tsc) followed by `npm test`, so a file that
|
|
58
|
+
fails type-checking or breaks a test cannot land on `master`.
|
|
59
|
+
|
|
20
60
|
# Code of Conduct
|
|
21
61
|
|
|
22
62
|
## Our Pledge
|
package/Dockerfile
CHANGED
package/README.md
CHANGED
|
@@ -40,28 +40,89 @@ Please see the [Documentation](https://vod2live.docs.eyevinn.technology) for int
|
|
|
40
40
|
- Develop adapters to plugin with custom scheduling endpoints
|
|
41
41
|
- High Availability with Redis Cache or Valkey as shared state store
|
|
42
42
|
- Support for WebVTT subtitles
|
|
43
|
-
- Support for DRM encrypted HLS VODs (in beta)
|
|
43
|
+
- Support for Widevine DRM encrypted HLS+CMAF VODs (in beta); see `examples/drm.ts`
|
|
44
44
|
- Improved performance with Redis connection pooling and pipelining
|
|
45
45
|
- Enhanced stability in High Availability mode
|
|
46
46
|
- Support for livemix with demuxed content (TS and CMAF)
|
|
47
|
+
- Support for SGAI HLS-interstitial ad breaks with client-side ad replacement
|
|
47
48
|
- And much more!
|
|
48
49
|
|
|
50
|
+
### Ad breaks (HLS interstitials)
|
|
51
|
+
|
|
52
|
+
A channel can be configured to open SGAI HLS-interstitial ad breaks. When
|
|
53
|
+
enabled, the engine emits EXT-X-DATERANGE interstitial metadata on the
|
|
54
|
+
manifest and resolves the ad asset from a configured ad-serving endpoint, with
|
|
55
|
+
a slate fallback if that endpoint cannot be reached. Configure it through the
|
|
56
|
+
`adBreak` option (engine-level default or per channel); see
|
|
57
|
+
[docs/reference.md](docs/reference.md#ad-break-configuration-hls-interstitials)
|
|
58
|
+
for the full field reference and `examples/adbreak.ts` for a runnable example.
|
|
59
|
+
|
|
60
|
+
### Custom VOD request parameters
|
|
61
|
+
|
|
62
|
+
The engine can be configured with an allowlist of query-parameter names that
|
|
63
|
+
are permitted to be forwarded to the asset manager's `getNextVod()` request,
|
|
64
|
+
through the `customVodRequestParams` option on `ChannelEngineOpts`. Only
|
|
65
|
+
parameters named in the allowlist may be passed through; all others are
|
|
66
|
+
ignored, and the default (option omitted) is an empty allowlist with no
|
|
67
|
+
pass-through. See
|
|
68
|
+
[docs/reference.md](docs/reference.md#custom-vod-request-parameters) for the
|
|
69
|
+
field reference.
|
|
70
|
+
|
|
71
|
+
Declare the allowlist when creating the engine and read the forwarded values
|
|
72
|
+
from `vodRequest.customParams` in your asset manager's `getNextVod()`:
|
|
73
|
+
|
|
74
|
+
```js
|
|
75
|
+
const { ChannelEngine } = require('eyevinn-channel-engine');
|
|
76
|
+
|
|
77
|
+
class MyAssetManager {
|
|
78
|
+
getNextVod(vodRequest) {
|
|
79
|
+
// Only allowlisted params are present; everything else is stripped.
|
|
80
|
+
// `customParams` is omitted entirely when no allowlisted param was sent.
|
|
81
|
+
const myparam = vodRequest.customParams && vodRequest.customParams.myparam;
|
|
82
|
+
return Promise.resolve({
|
|
83
|
+
id: '1',
|
|
84
|
+
title: 'Example',
|
|
85
|
+
uri: myparam
|
|
86
|
+
? `https://vod.example.com/${myparam}/master.m3u8`
|
|
87
|
+
: 'https://vod.example.com/default/master.m3u8'
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const engine = new ChannelEngine(new MyAssetManager(), {
|
|
93
|
+
channelManager: myChannelManager,
|
|
94
|
+
// Allowlist the query-parameter names to forward to getNextVod().
|
|
95
|
+
customVodRequestParams: ['myparam']
|
|
96
|
+
});
|
|
97
|
+
engine.start();
|
|
98
|
+
engine.listen(8000);
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
A request such as:
|
|
102
|
+
|
|
103
|
+
```
|
|
104
|
+
GET /channels/1/master.m3u8?myparam=foo
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
forwards `{ myparam: 'foo' }` to `getNextVod()` via `vodRequest.customParams`.
|
|
108
|
+
Any query parameter not in `customVodRequestParams` (e.g. `?other=bar`) is
|
|
109
|
+
dropped before it reaches the asset manager.
|
|
110
|
+
|
|
49
111
|
## System Requirements
|
|
50
112
|
|
|
51
113
|
Supported Node.js Versions
|
|
52
114
|
|
|
53
115
|
| Version | Supported |
|
|
54
116
|
| ------- | --------- |
|
|
55
|
-
|
|
|
56
|
-
|
|
|
57
|
-
| 18.x | Yes |
|
|
117
|
+
| 22.x | Yes |
|
|
118
|
+
| 24.x | Yes |
|
|
58
119
|
|
|
59
120
|
## Supported Source Formats
|
|
60
121
|
|
|
61
|
-
| HLS Format | Muxed | Demuxed | Mix w. Live | Subtitles | Mix w. Live & Subtitles | DRM
|
|
62
|
-
| ---------- | ----- | ------- | ----------- | --------- | ----------------------- |
|
|
63
|
-
| HLS + TS | Yes | Yes | Yes | Yes | No | No
|
|
64
|
-
| HLS + CMAF | Yes | Yes | Yes | Yes | No |
|
|
122
|
+
| HLS Format | Muxed | Demuxed | Mix w. Live | Subtitles | Mix w. Live & Subtitles | DRM |
|
|
123
|
+
| ---------- | ----- | ------- | ----------- | --------- | ----------------------- | -------------- |
|
|
124
|
+
| HLS + TS | Yes | Yes | Yes | Yes | No | No |
|
|
125
|
+
| HLS + CMAF | Yes | Yes | Yes | Yes | No | Yes (Widevine) |
|
|
65
126
|
|
|
66
127
|
NOTE: The engine does not support subtitles in the live-mix + demux setting. Furthermore, then using the live-mix + demux setting, it is most optimal to use HLS content which has the same segment durations on all variants.
|
|
67
128
|
Using a mix of different segment durations may result in occasional playback/audio sync issues, but not always. Further development will be needed to resolve this and improve the robustness of the live-mix + demux experience.
|
|
@@ -198,6 +259,7 @@ In addition there other reference implemetations that can be used:
|
|
|
198
259
|
- `examples/drm.ts` : example with DRM
|
|
199
260
|
- `examples/autocreate.ts` : example to auto create channel on demand
|
|
200
261
|
- `examples/truncate.ts` : example when trimming start and end of a VOD
|
|
262
|
+
- `examples/adbreak.ts` : example with a channel configured for HLS-interstitial ad breaks
|
|
201
263
|
|
|
202
264
|
### Source linking hls-vodtolive library
|
|
203
265
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export
|
|
1
|
+
export {};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
2
3
|
const debug = require('debug')('chaos-monkey');
|
|
3
4
|
const CHAOS_MONKEY_PROBABILITY = process.env.CHAOS_MONKEY_PROBABILITY || 0.5;
|
|
4
5
|
const doChaos = () => process.env.CHAOS_MONKEY === "true" && Math.random() < CHAOS_MONKEY_PROBABILITY;
|
|
@@ -1,13 +1 @@
|
|
|
1
|
-
export
|
|
2
|
-
declare class MemcachedStateStore {
|
|
3
|
-
constructor(keyPrefix: any, opts: any);
|
|
4
|
-
keyPrefix: any;
|
|
5
|
-
client: any;
|
|
6
|
-
initAsync(id: any, initData: any): Promise<{}>;
|
|
7
|
-
resetAsync(id: any, initData: any): Promise<void>;
|
|
8
|
-
resetAllAsync(): Promise<void>;
|
|
9
|
-
getAsync(id: any, key: any): Promise<any>;
|
|
10
|
-
setAsync(id: any, key: any, value: any): Promise<any>;
|
|
11
|
-
setVolatileAsync(id: any, key: any, value: any): Promise<void>;
|
|
12
|
-
removeAsync(id: any, key: any): Promise<void>;
|
|
13
|
-
}
|
|
1
|
+
export {};
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
2
3
|
const MemcacheClient = require("memcache-client");
|
|
3
4
|
const debug = require("debug")("memcached-state-store");
|
|
5
|
+
// Type-only migration (#373): a faithful port of the original JS.
|
|
4
6
|
class MemcachedStateStore {
|
|
7
|
+
keyPrefix;
|
|
8
|
+
client;
|
|
5
9
|
constructor(keyPrefix, opts) {
|
|
6
10
|
this.keyPrefix = keyPrefix;
|
|
7
11
|
if (opts.version) {
|
|
@@ -1,13 +1 @@
|
|
|
1
|
-
export
|
|
2
|
-
declare class MemoryStateStore {
|
|
3
|
-
constructor(type: any, opts: any);
|
|
4
|
-
sharedStates: {};
|
|
5
|
-
globalSharedStates: {};
|
|
6
|
-
initAsync(id: any, initData: any): Promise<any>;
|
|
7
|
-
resetAsync(id: any, initData: any): Promise<void>;
|
|
8
|
-
resetAllAsync(): Promise<void>;
|
|
9
|
-
getAsync(id: any, key: any): Promise<any>;
|
|
10
|
-
setAsync(id: any, key: any, value: any): Promise<any>;
|
|
11
|
-
setVolatileAsync(id: any, key: any, value: any): Promise<any>;
|
|
12
|
-
removeAsync(id: any, key: any): Promise<void>;
|
|
13
|
-
}
|
|
1
|
+
export {};
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
2
3
|
const debug = require("debug")("memory-state-store");
|
|
4
|
+
// Type-only migration (#373): a faithful port of the original JS. Runtime
|
|
5
|
+
// behavior and the exported constructor signature are unchanged.
|
|
3
6
|
class MemoryStateStore {
|
|
7
|
+
sharedStates;
|
|
8
|
+
globalSharedStates;
|
|
4
9
|
constructor(type, opts) {
|
|
5
10
|
this.sharedStates = {};
|
|
6
11
|
this.globalSharedStates = {};
|
|
@@ -1,27 +1 @@
|
|
|
1
|
-
export const PlayheadState: Readonly<{
|
|
2
|
-
RUNNING: 1;
|
|
3
|
-
STOPPED: 2;
|
|
4
|
-
CRASHED: 3;
|
|
5
|
-
IDLE: 4;
|
|
6
|
-
}>;
|
|
7
|
-
export class PlayheadStateStore extends SharedStateStore {
|
|
8
|
-
constructor(opts: any);
|
|
9
|
-
create(sessionId: any): Promise<SharedPlayheadState>;
|
|
10
|
-
}
|
|
11
|
-
import SharedStateStore = require("./shared_state_store.js");
|
|
12
|
-
declare class SharedPlayheadState {
|
|
13
|
-
constructor(store: any, sessionId: any, opts: any);
|
|
14
|
-
sessionId: any;
|
|
15
|
-
store: any;
|
|
16
|
-
state: 4;
|
|
17
|
-
lastM3u8: any;
|
|
18
|
-
get(key: any): Promise<any>;
|
|
19
|
-
getState(): Promise<4>;
|
|
20
|
-
getLastM3u8(): Promise<any>;
|
|
21
|
-
getValues(keys: any): Promise<any>;
|
|
22
|
-
set(key: any, value: any, isLeader: any): Promise<any>;
|
|
23
|
-
setValues(keyValues: any, isLeader: any): Promise<any>;
|
|
24
|
-
setState(newState: any): Promise<4>;
|
|
25
|
-
setLastM3u8(m3u8: any): Promise<any>;
|
|
26
|
-
}
|
|
27
1
|
export {};
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
2
3
|
const SharedStateStore = require('./shared_state_store.js');
|
|
4
|
+
// Type-only migration (#373): a faithful port of the original JS.
|
|
5
|
+
// `SharedStateStore` is loaded via CommonJS `require` (erasable syntax) so the
|
|
6
|
+
// still-`.js` consumers keep resolving it unchanged; the base type is `any` at
|
|
7
|
+
// this interop boundary.
|
|
3
8
|
const PlayheadState = Object.freeze({
|
|
4
9
|
RUNNING: 1,
|
|
5
10
|
STOPPED: 2,
|
|
@@ -7,6 +12,10 @@ const PlayheadState = Object.freeze({
|
|
|
7
12
|
IDLE: 4
|
|
8
13
|
});
|
|
9
14
|
class SharedPlayheadState {
|
|
15
|
+
sessionId;
|
|
16
|
+
store;
|
|
17
|
+
state;
|
|
18
|
+
lastM3u8;
|
|
10
19
|
constructor(store, sessionId, opts) {
|
|
11
20
|
this.sessionId = sessionId;
|
|
12
21
|
this.store = store;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export
|
|
1
|
+
export {};
|
package/dist/engine/preflight.js
CHANGED
|
@@ -1,19 +1 @@
|
|
|
1
|
-
export
|
|
2
|
-
declare class RedisStateStore {
|
|
3
|
-
constructor(keyPrefix: any, opts: any);
|
|
4
|
-
keyPrefix: any;
|
|
5
|
-
volatileKeyTTL: any;
|
|
6
|
-
pool: any[];
|
|
7
|
-
createRedisPool(size: any, redisUrl: any): any[];
|
|
8
|
-
getClientFromPool(maxWaitTime?: number): Promise<any>;
|
|
9
|
-
returnClientToPool(client: any): void;
|
|
10
|
-
initAsync(id: any, initData: any): Promise<{}>;
|
|
11
|
-
resetAsync(id: any, initData: any): Promise<void>;
|
|
12
|
-
resetAllAsync(): Promise<void>;
|
|
13
|
-
getValues(id: any, keys: any): Promise<{}>;
|
|
14
|
-
getAsync(id: any, key: any): Promise<any>;
|
|
15
|
-
setValues(id: any, data: any): Promise<{}>;
|
|
16
|
-
setAsync(id: any, key: any, value: any): Promise<any>;
|
|
17
|
-
setVolatileAsync(id: any, key: any, value: any): Promise<any>;
|
|
18
|
-
removeAsync(id: any, key: any): Promise<any>;
|
|
19
|
-
}
|
|
1
|
+
export {};
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
2
3
|
const Redis = require("ioredis");
|
|
3
4
|
const debug = require("debug")("redis-state-store");
|
|
4
5
|
const { cloudWatchLog, timer } = require("./util.js");
|
|
6
|
+
// Type-only migration (#373): a faithful port of the original JS.
|
|
5
7
|
const DEFAULT_VOLATILE_KEY_TTL = 5; // Timeout so it should not expire within one normal increment iteration (in seconds)
|
|
6
8
|
function isTrue(s) {
|
|
7
9
|
const regex = /^\s*(true|1)\s*$/i;
|
|
@@ -10,6 +12,9 @@ function isTrue(s) {
|
|
|
10
12
|
const REDIS_VERBOSE_LOG = process.env.REDIS_VERBOSE_LOG ? isTrue(process.env.REDIS_VERBOSE_LOG) : false;
|
|
11
13
|
const REDIS_POOL_SIZE = process.env.REDIS_POOL_SIZE ? parseInt(process.env.REDIS_POOL_SIZE) : 15;
|
|
12
14
|
class RedisStateStore {
|
|
15
|
+
keyPrefix;
|
|
16
|
+
volatileKeyTTL;
|
|
17
|
+
pool;
|
|
13
18
|
constructor(keyPrefix, opts) {
|
|
14
19
|
this.keyPrefix = keyPrefix;
|
|
15
20
|
if (opts.version) {
|
package/dist/engine/server.d.ts
CHANGED
|
@@ -1,7 +1,18 @@
|
|
|
1
|
+
export interface AdBreakOpts {
|
|
2
|
+
enabled: boolean;
|
|
3
|
+
adServerUri?: string;
|
|
4
|
+
slate?: SlateOpts;
|
|
5
|
+
}
|
|
6
|
+
export interface SlateOpts {
|
|
7
|
+
uri: string;
|
|
8
|
+
repetitions?: number;
|
|
9
|
+
duration?: number;
|
|
10
|
+
}
|
|
1
11
|
export interface ChannelEngineOpts {
|
|
2
12
|
defaultSlateUri?: string;
|
|
3
13
|
slateRepetitions?: number;
|
|
4
14
|
slateDuration?: number;
|
|
15
|
+
adBreak?: AdBreakOpts;
|
|
5
16
|
redisUrl?: string;
|
|
6
17
|
memcachedUrl?: string;
|
|
7
18
|
sharedStoreCacheTTL?: number;
|
|
@@ -35,11 +46,19 @@ export interface ChannelEngineOpts {
|
|
|
35
46
|
sessionEventStream?: boolean;
|
|
36
47
|
sessionHealthKey?: string;
|
|
37
48
|
rollingPDT?: boolean;
|
|
49
|
+
event?: boolean;
|
|
50
|
+
customVodRequestParams?: string[];
|
|
51
|
+
streamSwitchTimeIntervalMs?: number;
|
|
52
|
+
streamSwitchOngoingEventIntervalMs?: number;
|
|
53
|
+
streamSwitchNearEndEventIntervalMs?: number;
|
|
38
54
|
}
|
|
39
55
|
export interface VodRequest {
|
|
40
56
|
sessionId: string;
|
|
41
57
|
category?: string;
|
|
42
58
|
playlistId: string;
|
|
59
|
+
customParams?: {
|
|
60
|
+
[key: string]: string;
|
|
61
|
+
};
|
|
43
62
|
}
|
|
44
63
|
export interface VodResponseMetadata {
|
|
45
64
|
id: string;
|
|
@@ -86,6 +105,8 @@ export interface Channel {
|
|
|
86
105
|
audioTracks?: AudioTracks[];
|
|
87
106
|
subtitleTracks?: SubtitleTracks[];
|
|
88
107
|
closedCaptions?: ClosedCaptions[];
|
|
108
|
+
slate?: SlateOpts;
|
|
109
|
+
adBreak?: AdBreakOpts;
|
|
89
110
|
}
|
|
90
111
|
export interface ClosedCaptions {
|
|
91
112
|
id: string;
|
|
@@ -138,6 +159,7 @@ export declare class ChannelEngine {
|
|
|
138
159
|
private alwaysMapBandwidthByNearest;
|
|
139
160
|
private defaultSlateUri?;
|
|
140
161
|
private slateDuration?;
|
|
162
|
+
private adBreak?;
|
|
141
163
|
private assetMgr;
|
|
142
164
|
private streamSwitchManager?;
|
|
143
165
|
private slateRepetitions?;
|
|
@@ -146,6 +168,8 @@ export declare class ChannelEngine {
|
|
|
146
168
|
private serverStartTime;
|
|
147
169
|
private instanceId;
|
|
148
170
|
private streamSwitchTimeIntervalMs;
|
|
171
|
+
private streamSwitchOngoingEventIntervalMs;
|
|
172
|
+
private streamSwitchNearEndEventIntervalMs;
|
|
149
173
|
private sessionStore;
|
|
150
174
|
private sessionLiveStore;
|
|
151
175
|
private streamerOpts;
|
|
@@ -156,7 +180,10 @@ export declare class ChannelEngine {
|
|
|
156
180
|
private sessionResetKey;
|
|
157
181
|
private sessionEventStream;
|
|
158
182
|
private sessionHealthKey;
|
|
183
|
+
private customVodRequestParams;
|
|
184
|
+
private static normalizeAdBreak;
|
|
159
185
|
constructor(assetMgr: IAssetManager, options?: ChannelEngineOpts);
|
|
186
|
+
computeStreamSwitchIntervalMs(baseIntervalMs: any): any;
|
|
160
187
|
updateStreamSwitchAsync(): Promise<void>;
|
|
161
188
|
updateChannelsAsync(channelMgr: any, options: any): Promise<void>;
|
|
162
189
|
start(): void;
|