eyevinn-channel-engine 5.1.2 → 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.
Files changed (97) hide show
  1. package/.github/workflows/nodejs.yml +1 -1
  2. package/.github/workflows/publish.yml +1 -1
  3. package/.github/workflows/rc.yml +1 -1
  4. package/CONTRIBUTING.md +40 -0
  5. package/Dockerfile +1 -1
  6. package/README.md +70 -8
  7. package/dist/engine/chaos_monkey.d.ts +1 -1
  8. package/dist/engine/chaos_monkey.js +1 -0
  9. package/dist/engine/event_stream.d.ts +1 -6
  10. package/dist/engine/event_stream.js +2 -0
  11. package/dist/engine/memcached_state_store.d.ts +1 -13
  12. package/dist/engine/memcached_state_store.js +4 -0
  13. package/dist/engine/memory_state_store.d.ts +1 -13
  14. package/dist/engine/memory_state_store.js +5 -0
  15. package/dist/engine/playhead_state.d.ts +0 -26
  16. package/dist/engine/playhead_state.js +9 -0
  17. package/dist/engine/preflight.d.ts +1 -1
  18. package/dist/engine/preflight.js +1 -0
  19. package/dist/engine/redis_state_store.d.ts +1 -19
  20. package/dist/engine/redis_state_store.js +5 -0
  21. package/dist/engine/server.d.ts +27 -0
  22. package/dist/engine/server.js +140 -6
  23. package/dist/engine/session.d.ts +1 -148
  24. package/dist/engine/session.js +398 -11
  25. package/dist/engine/session_live.d.ts +1 -181
  26. package/dist/engine/session_live.js +19 -4
  27. package/dist/engine/session_live_state.d.ts +0 -23
  28. package/dist/engine/session_live_state.js +5 -0
  29. package/dist/engine/session_state.d.ts +0 -45
  30. package/dist/engine/session_state.js +10 -0
  31. package/dist/engine/shared_state_store.d.ts +1 -25
  32. package/dist/engine/shared_state_store.js +10 -0
  33. package/dist/engine/state_store_types.d.ts +32 -0
  34. package/dist/engine/state_store_types.js +5 -0
  35. package/dist/engine/stream_switcher.d.ts +1 -40
  36. package/dist/engine/stream_switcher.js +108 -20
  37. package/dist/engine/subtitle_slicer.d.ts +1 -8
  38. package/dist/engine/subtitle_slicer.js +1 -0
  39. package/dist/engine/util.d.ts +1 -29
  40. package/dist/engine/util.js +2 -1
  41. package/dist/examples/adbreak.d.ts +1 -0
  42. package/dist/examples/adbreak.js +104 -0
  43. package/dist/index.d.ts +1 -1
  44. package/dist/package.json +20 -4
  45. package/docs/design/mixing-muxed-demuxed-audio.md +153 -0
  46. package/docs/design/subtitles-live-mix-demux.md +135 -0
  47. package/docs/reference.md +67 -0
  48. package/engine/chaos_monkey.ts +17 -0
  49. package/engine/{event_stream.js → event_stream.ts} +5 -3
  50. package/engine/{memcached_state_store.js → memcached_state_store.ts} +19 -12
  51. package/engine/memory_state_store.ts +71 -0
  52. package/engine/{playhead_state.js → playhead_state.ts} +92 -82
  53. package/engine/{preflight.js → preflight.ts} +1 -1
  54. package/engine/{redis_state_store.js → redis_state_store.ts} +216 -208
  55. package/engine/server.ts +210 -8
  56. package/engine/{session.js → session.ts} +421 -22
  57. package/engine/{session_live.js → session_live.ts} +54 -31
  58. package/engine/{session_live_state.js → session_live_state.ts} +129 -120
  59. package/engine/{session_state.js → session_state.ts} +269 -248
  60. package/engine/{shared_state_store.js → shared_state_store.ts} +31 -19
  61. package/engine/state_store_types.ts +35 -0
  62. package/engine/{stream_switcher.js → stream_switcher.ts} +133 -34
  63. package/engine/{subtitle_slicer.js → subtitle_slicer.ts} +10 -8
  64. package/engine/{util.js → util.ts} +28 -24
  65. package/examples/adbreak.ts +115 -0
  66. package/index.ts +2 -0
  67. package/package.json +20 -4
  68. package/spec/engine/custom_vod_request_params_spec.ts +99 -0
  69. package/spec/engine/drm_spec.ts +128 -0
  70. package/spec/engine/{engine_spec.js → engine_spec.ts} +44 -1
  71. package/spec/engine/{ha_spec.js → ha_spec.ts} +7 -4
  72. package/spec/engine/{init_switching_spec.js → init_switching_spec.ts} +10 -6
  73. package/spec/engine/{interface_spec.js → interface_spec.ts} +16 -4
  74. package/spec/engine/{playhead_live_spec.js → playhead_live_spec.ts} +2 -1
  75. package/spec/engine/{playhead_spec.js → playhead_spec.ts} +15 -8
  76. package/spec/engine/session_spec.ts +800 -0
  77. package/spec/engine/stream_switcher_audio_reconcile_spec.ts +158 -0
  78. package/spec/engine/{stream_switcher_spec.js → stream_switcher_spec.ts} +111 -13
  79. package/spec/engine/subtitle_missing_language_spec.ts +196 -0
  80. package/spec/engine/{subtitle_spec.js → subtitle_spec.ts} +28 -27
  81. package/spec/helpers/ts-resolve.js +65 -0
  82. package/spec/support/jasmine.json +1 -1
  83. package/spec/testvectors/hls_subs_no_language/config.subtitleTracks.json +12 -0
  84. package/spec/testvectors/hls_subs_no_language/evidence_dummy_segments_name_mismatch.m3u8 +24 -0
  85. package/spec/testvectors/hls_subs_no_language/evidence_real_cues_name_match.m3u8 +24 -0
  86. package/spec/testvectors/hls_subs_no_language/french.m3u8 +9 -0
  87. package/spec/testvectors/hls_subs_no_language/master.m3u8 +11 -0
  88. package/spec/testvectors/hls_subs_no_language/video.m3u8 +25 -0
  89. package/spec/testvectors/slate/master.m3u8 +3 -0
  90. package/spec/testvectors/slate/media.m3u8 +9 -0
  91. package/tsconfig.json +21 -4
  92. package/tsconfig.spec.json +16 -0
  93. package/engine/chaos_monkey.js +0 -17
  94. package/engine/memory_state_store.js +0 -63
  95. package/spec/engine/session_spec.js +0 -116
  96. /package/spec/engine/{session_live_spec.js → session_live_spec.ts} +0 -0
  97. /package/spec/engine/{util_spec.js → util_spec.ts} +0 -0
@@ -1,181 +1 @@
1
- export = SessionLive;
2
- /**
3
- * When we implement subtitle support in live-mix we should place it in its own file/or share it with audio
4
- * we should also remove audio implementation when we implement subtitles from this file so we don't get at 4000 line long file.
5
- */
6
- declare class SessionLive {
7
- constructor(config: any, sessionLiveStore: any);
8
- sessionId: any;
9
- sessionLiveStateStore: any;
10
- instanceId: any;
11
- mediaSeqCountVideo: number;
12
- mediaSeqCountAudio: number;
13
- prevMediaSeqCountVideo: number;
14
- prevMediaSeqCountAudio: number;
15
- discSeqCountVideo: number;
16
- discSeqCountAudio: number;
17
- prevDiscSeqCountVideo: number;
18
- prevDiscSeqCountAudio: number;
19
- targetDuration: number;
20
- masterManifestUri: string;
21
- vodSegments: {};
22
- vodSegmentsAudio: {};
23
- mediaManifestURIs: {};
24
- audioManifestURIs: {};
25
- liveSegQueue: {};
26
- lastRequestedMediaSeqRawVideo: any;
27
- prevSeqBottomVideoSegUri: any;
28
- prevSeqBottomAudioSegUri: any;
29
- liveSourceM3Us: {};
30
- liveSegQueueAudio: {};
31
- lastRequestedMediaSeqRawAudio: any;
32
- liveAudioSourceM3Us: {};
33
- playheadState: 4;
34
- liveSegsForFollowers: {};
35
- liveSegsForFollowersAudio: {};
36
- timerCompensation: boolean;
37
- firstTime: boolean;
38
- firstTimeAudio: boolean;
39
- allowedToSet: boolean;
40
- pushAmount: number;
41
- restAmount: number;
42
- pushAmountAudio: number;
43
- restAmountAudio: number;
44
- waitForPlayhead: boolean;
45
- blockGenerateManifest: boolean;
46
- timeOffsetVideo: number;
47
- timeOffsetAudio: number;
48
- v2lHasTimelinePosition: boolean;
49
- useDemuxedAudio: boolean;
50
- cloudWatchLogging: boolean;
51
- sessionLiveProfile: any;
52
- sessionAudioTracks: any;
53
- initAsync(): Promise<void>;
54
- sessionLiveState: any;
55
- /**
56
- *
57
- * @param {number} resetDelay The amount of time to wait before resetting the session.
58
- *
59
- */
60
- resetLiveStoreAsync(resetDelay: number): Promise<void>;
61
- resetSession(): Promise<void>;
62
- startPlayheadAsync(): Promise<void>;
63
- restartPlayheadAsync(): Promise<void>;
64
- stopPlayheadAsync(): Promise<void>;
65
- /**
66
- * This function sets the master manifest URI in sessionLive.
67
- * @param {string} masterManifestUri The master manifest URI.
68
- * @returns a boolean indicating whether the master manifest URI is reachable or not.
69
- */
70
- setLiveUri(masterManifestUri: string): Promise<boolean>;
71
- setCurrentMediaSequenceSegments(segments: any): Promise<boolean>;
72
- setCurrentAudioSequenceSegments(segments: any): Promise<boolean>;
73
- setCurrentMediaAndDiscSequenceCount(mediaSeq: any, discSeq: any, audioMediaSeq: any, audioDiscSeq: any): Promise<boolean>;
74
- getTransitionalSegments(): Promise<{}>;
75
- getTransitionalAudioSegments(): Promise<{}>;
76
- getCurrentMediaSequenceSegments(): Promise<{
77
- currMseqSegs: {};
78
- segCount: number;
79
- }>;
80
- getCurrentAudioSequenceSegments(): Promise<{
81
- currMseqSegs: {};
82
- segCount: number;
83
- }>;
84
- getCurrentMediaAndDiscSequenceCount(): Promise<{
85
- mediaSeq: number;
86
- discSeq: number;
87
- }>;
88
- getStatus(): {
89
- sessionId: any;
90
- playhead: {
91
- state: any;
92
- };
93
- };
94
- getCurrentMediaManifestAsync(bw: any): Promise<string>;
95
- getCurrentAudioManifestAsync(audioGroupId: any, audioLanguage: any): Promise<string>;
96
- getCurrentSubtitleManifestAsync(subtitleGroupId: any, subtitleLanguage: any): Promise<string>;
97
- /**
98
- *
99
- * @param {string} masterManifestURI The master manifest URI.
100
- * @returns Loads the URIs to the different media playlists from the given master playlist.
101
- *
102
- */
103
- _loadMasterManifest(masterManifestURI: string): Promise<any>;
104
- _updateLiveSegQueue(): Promise<never>;
105
- _updateLiveSegQueueAudio(): Promise<never>;
106
- _collectSegmentsFromStore(): Promise<never>;
107
- _fetchFromLiveSource(): Promise<{
108
- success: boolean;
109
- currentMseqRaw: any;
110
- }>;
111
- _parseFromLiveSource(current_mediasequence_raw: any): Promise<never>;
112
- /**
113
- * This function adds new live segments to the node from which it can
114
- * generate new manifests from. Method for attaining new segments differ
115
- * depending on node Rank. The Leader collects from live source and
116
- * Followers collect from shared storage.
117
- */
118
- _loadAllPlaylistManifests(): Promise<void>;
119
- _shiftSegments(opt: any): {
120
- totalDuration: number;
121
- removedSegments: number;
122
- removedDiscontinuities: number;
123
- shiftedSegments: {};
124
- };
125
- _shiftVariantSegments(variantKeys: any, _name: any, _segments: any): {
126
- timeToRemove: number;
127
- incrementDiscSeqCount: boolean;
128
- segments: any;
129
- };
130
- /**
131
- * Shifts V2L or LIVE items if total segment duration (V2L+LIVE) are over the target duration.
132
- * It will also update and increment SessionLive's mediaSeqCountVideo and DiscSeqCount based
133
- * on what was shifted.
134
- * @param {string} instanceName Name of instance "LEADER" | "FOLLOWER"
135
- * @returns {number} The new total duration in seconds
136
- */
137
- _incrementAndShift(instanceName: string): number;
138
- _incrementAndShiftAudio(instanceName: any): number;
139
- _loadMediaManifest(bw: any): Promise<any>;
140
- _loadAudioManifest(audiotrack: any): Promise<any>;
141
- _pushAmountBasedOnPreviousLastSegmentURI(m3u: any, isFirstTrack: any): number;
142
- _parseMediaManifest(m3u: any, mediaManifestUri: any, liveTargetBandwidth: any, isFirstBW: any, isLeader: any): Promise<any>;
143
- _parseAudioManifest(m3u: any, audioPlaylistUri: any, liveTargetAudiotrack: any, isFirstAT: any, isLeader: any): Promise<any>;
144
- /**
145
- * Collects 'new' PlaylistItems and converts them into custom SegmentItems,
146
- * then Pushes them to the LiveSegQueue for all variants.
147
- * @param {number} startIdx
148
- * @param {m3u8.Item.PlaylistItem} playlistItems
149
- * @param {string} baseUrl
150
- * @param {string} liveTargetBandwidth
151
- */
152
- _addLiveSegmentsToQueue(isFirst: any, startIdx: number, playlistItems: m3u8.Item.PlaylistItem, baseUrl: string, liveTargetVariant: any, isLeader: any, plType: any): Promise<never>;
153
- _pushToQueue(seg: any, liveTargetBandwidth: any, logName: any): void;
154
- _pushToQueueAudio(seg: any, liveTargetAudiotrack: any, logName: any): void;
155
- _GenerateLiveManifest(bw: any): Promise<string>;
156
- _GenerateLiveAudioManifest(audioGroupId: any, audioLanguage: any): Promise<string>;
157
- _setVariantManifestSegmentTags(segments: any, m3u8: any, variantKey: any): any;
158
- _findNearestBw(bw: any, array: any): any;
159
- _getNearestBandwidth(bandwidthToMatch: any, array: any): any;
160
- _getFirstBwWithSegmentsInList(allSegments: any): string;
161
- _findAudioGroupsForLang(audioLanguage: any, segments: any): {
162
- audioGroupId: string;
163
- audioLanguage: string;
164
- }[];
165
- _findNearestAudiotrack(track: any, tracks: any): any;
166
- _getMaxDuration(segments: any): number;
167
- _filterLiveProfiles(): void;
168
- _filterLiveProfilesAudio(): void;
169
- _filterLiveAudioTracks(): void;
170
- _getAnyFirstSegmentDurationMs(): number;
171
- _isEmpty(obj: any): boolean;
172
- _containsSegment(segments: any, newSegments: any): boolean;
173
- _getGroupAndLangFromTrack(track: any): {
174
- groupId: any;
175
- language: any;
176
- };
177
- _getLangFromTrack(track: any): any;
178
- _getGroupFromTrack(track: any): any;
179
- _getTrackFromGroupAndLang(g: any, l: any): string;
180
- _isBandwidth(bw: any): boolean;
181
- }
1
+ export {};
@@ -1,4 +1,5 @@
1
1
  "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
2
3
  const debug = require("debug")("engine-session-live");
3
4
  const allSettled = require("promise.allsettled");
4
5
  const crypto = require("crypto");
@@ -226,7 +227,7 @@ class SessionLive {
226
227
  }
227
228
  catch (err) {
228
229
  debug(`[${this.sessionId}]: SessionLive-Playhead consumer crashed`);
229
- console.error(`[${this.sessionId}]: ${err.message}`);
230
+ console.error(`[${this.sessionId}]: ${err instanceof Error ? err.message : err}`);
230
231
  debug(err);
231
232
  this.playheadState = PlayheadState.CRASHED;
232
233
  }
@@ -873,7 +874,7 @@ class SessionLive {
873
874
  break;
874
875
  }
875
876
  const segDur = this._getAnyFirstSegmentDurationMs() || DEFAULT_PLAYHEAD_INTERVAL_MS;
876
- const waitTimeMs = parseInt(segDur / 3, 10);
877
+ const waitTimeMs = parseInt((segDur / 3), 10);
877
878
  debug(`[${this.sessionId}]: FOLLOWER: Leader has not put anything in store... Will check again in ${waitTimeMs}ms (Tries left=[${attempts}])`);
878
879
  await timer(waitTimeMs);
879
880
  this.timerCompensation = false;
@@ -895,7 +896,7 @@ class SessionLive {
895
896
  break;
896
897
  }
897
898
  const segDur = this._getAnyFirstSegmentDurationMs() || DEFAULT_PLAYHEAD_INTERVAL_MS;
898
- const waitTimeMs = parseInt(segDur / 3, 10);
899
+ const waitTimeMs = parseInt((segDur / 3), 10);
899
900
  debug(`[${this.sessionId}]: FOLLOWER: Leader has not put anything audio in store... Will check again in ${waitTimeMs}ms (Tries left=[${attempts}])`);
900
901
  await timer(waitTimeMs);
901
902
  this.timerCompensation = false;
@@ -932,7 +933,7 @@ class SessionLive {
932
933
  debug(`[${this.sessionId}]: FOLLOWER: _containsSegment=true,V[${leadersMediaSeqRaw}],[${this.lastRequestedMediaSeqRawVideo}]${hasAudio ? `,A[${leadersMediaSeqRawAudio}],[${this.lastRequestedMediaSeqRawAudio}]` : ""}`);
933
934
  }
934
935
  const segDur = this._getAnyFirstSegmentDurationMs() || DEFAULT_PLAYHEAD_INTERVAL_MS;
935
- const waitTimeMs = parseInt(segDur / 3, 10);
936
+ const waitTimeMs = parseInt((segDur / 3), 10);
936
937
  debug(`[${this.sessionId}]: FOLLOWER: Cannot find anything NEW in store... Will check again in ${waitTimeMs}ms (Tries left=[${attempts}])`);
937
938
  await timer(waitTimeMs);
938
939
  this.timerCompensation = false;
@@ -1094,6 +1095,9 @@ class SessionLive {
1094
1095
  audiotracksToSkipOnRetry = [];
1095
1096
  debug(`[${this.sessionId}]: Live Mseq counts=[${allStoredMediaSeqCountsVideo}]`);
1096
1097
  // Figure out what variants's are behind.
1098
+ // @ts-ignore -- pre-existing behavior: `HIGHEST_MEDIA_SEQUENCE_COUNT`
1099
+ // is a module-level `const`; this assignment throws at runtime if ever
1100
+ // reached. Preserved byte-for-byte (type-only migration, #374).
1097
1101
  HIGHEST_MEDIA_SEQUENCE_COUNT = Math.max(...allStoredMediaSeqCountsVideo);
1098
1102
  Object.keys(this.liveSourceM3Us).map((variantKey) => {
1099
1103
  if (this.liveSourceM3Us[variantKey].mediaSeq === HIGHEST_MEDIA_SEQUENCE_COUNT) {
@@ -2184,6 +2188,9 @@ class SessionLive {
2184
2188
  }
2185
2189
  }
2186
2190
  if (!segAmounts.every((val, i, arr) => val === arr[0])) {
2191
+ // @ts-ignore -- pre-existing behavior: `console` is called as a function
2192
+ // here (not `console.log`), which throws at runtime if this path is hit.
2193
+ // Preserved byte-for-byte (type-only migration, #374).
2187
2194
  console(`[${this.sessionId}]: Cannot Generate audio Manifest! <${this.instanceId}> Not yet collected ALL segments from Live Source...`);
2188
2195
  return null;
2189
2196
  }
@@ -2373,6 +2380,8 @@ class SessionLive {
2373
2380
  let newItemsAudio = {};
2374
2381
  audioTracks.forEach((audioTrack) => {
2375
2382
  let groupAndLangToKeep = this._findAudioGroupsForLang(audioTrack.language, this.audioManifestURIs);
2383
+ // Cast to a 1-tuple so the (behavior-preserving) spread type-checks against
2384
+ // Set.add's single parameter; runtime is unchanged (extra elements ignored).
2376
2385
  toKeep.add(...groupAndLangToKeep);
2377
2386
  });
2378
2387
  toKeep.forEach((trackInfo) => {
@@ -2447,6 +2456,8 @@ class SessionLive {
2447
2456
  return GLItem;
2448
2457
  }
2449
2458
  }
2459
+ // @ts-ignore -- pre-existing behavior: `g`/`l` are block-scoped to the
2460
+ // `if (match)` block above and are not in scope here. Preserved as-is.
2450
2461
  console.error(`Failed to extract GroupID and Language g=${g};l=${l}`);
2451
2462
  return GLItem;
2452
2463
  }
@@ -2459,6 +2470,8 @@ class SessionLive {
2459
2470
  return l;
2460
2471
  }
2461
2472
  }
2473
+ // @ts-ignore -- pre-existing behavior: `g`/`l` are block-scoped to the
2474
+ // `if (match)` block above and are not in scope here. Preserved as-is.
2462
2475
  console.error(`Failed to extract Language g=${g};l=${l}`);
2463
2476
  return null;
2464
2477
  }
@@ -2471,6 +2484,8 @@ class SessionLive {
2471
2484
  return g;
2472
2485
  }
2473
2486
  }
2487
+ // @ts-ignore -- pre-existing behavior: `g`/`l` are block-scoped to the
2488
+ // `if (match)` block above and are not in scope here. Preserved as-is.
2474
2489
  console.error(`Failed to extract Group ID g=${g};l=${l}`);
2475
2490
  return null;
2476
2491
  }
@@ -1,24 +1 @@
1
- export class SessionLiveStateStore extends SharedStateStore {
2
- constructor(opts: any);
3
- cache: {
4
- leader: {
5
- ts: number;
6
- value: any;
7
- };
8
- };
9
- ping(instanceId: any): Promise<void>;
10
- setLeader(instanceId: any): Promise<any>;
11
- isLeader(instanceId: any): Promise<boolean>;
12
- create(sessionId: any, instanceId: any): Promise<SharedSessionLiveState>;
13
- }
14
- import SharedStateStore = require("./shared_state_store.js");
15
- declare class SharedSessionLiveState {
16
- constructor(store: any, sessionId: any, instanceId: any, opts: any);
17
- sessionId: any;
18
- instanceId: any;
19
- store: any;
20
- get(key: any): Promise<any>;
21
- set(key: any, value: any): Promise<any>;
22
- remove(key: any): Promise<void>;
23
- }
24
1
  export {};
@@ -1,7 +1,12 @@
1
1
  "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
2
3
  const SharedStateStore = require('./shared_state_store.js');
3
4
  const debug = require("debug")("session-live-state-store");
5
+ // Type-only migration (#373): a faithful port of the original JS.
4
6
  class SharedSessionLiveState {
7
+ sessionId;
8
+ instanceId;
9
+ store;
5
10
  constructor(store, sessionId, instanceId, opts) {
6
11
  this.sessionId = sessionId;
7
12
  this.instanceId = instanceId;
@@ -1,46 +1 @@
1
- export const SessionState: Readonly<{
2
- VOD_INIT: 1;
3
- VOD_PLAYING: 2;
4
- VOD_NEXT_INIT: 3;
5
- VOD_NEXT_INITIATING: 4;
6
- VOD_RELOAD_INIT: 5;
7
- VOD_RELOAD_INITIATING: 6;
8
- }>;
9
- export class SessionStateStore extends SharedStateStore {
10
- constructor(opts: any);
11
- cache: {
12
- leader: {
13
- ts: number;
14
- value: any;
15
- };
16
- };
17
- ping(instanceId: any): Promise<void>;
18
- clearLeaderCache(): Promise<void>;
19
- isLeader(instanceId: any): Promise<boolean>;
20
- create(sessionId: any, instanceId: any): Promise<SharedSessionState>;
21
- }
22
- import SharedStateStore = require("./shared_state_store.js");
23
- declare class SharedSessionState {
24
- constructor(store: any, sessionId: any, instanceId: any, opts: any);
25
- sessionId: any;
26
- instanceId: any;
27
- cache: {
28
- currentVod: {
29
- ts: number;
30
- ttl: number;
31
- value: any;
32
- };
33
- };
34
- cacheTTL: any;
35
- store: any;
36
- clearCurrentVodCache(): Promise<void>;
37
- getCurrentVod(): Promise<any>;
38
- setCurrentVod(hlsVod: any, opts: any): Promise<any>;
39
- get(key: any): Promise<any>;
40
- getValues(keys: any): Promise<any>;
41
- set(key: any, value: any): Promise<any>;
42
- setValues(keyValues: any): Promise<any>;
43
- remove(key: any): Promise<void>;
44
- increment(key: any, inc: any): Promise<any>;
45
- }
46
1
  export {};
@@ -1,8 +1,10 @@
1
1
  "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
2
3
  const HLSVod = require('@eyevinn/hls-vodtolive');
3
4
  const SharedStateStore = require('./shared_state_store.js');
4
5
  const debug = require("debug")("session-state-store");
5
6
  const { timeLeft } = require('./util.js');
7
+ // Type-only migration (#373): a faithful port of the original JS.
6
8
  const SessionState = Object.freeze({
7
9
  VOD_INIT: 1,
8
10
  VOD_PLAYING: 2,
@@ -13,6 +15,11 @@ const SessionState = Object.freeze({
13
15
  });
14
16
  const CURRENTVOD_CACHE_TTL = 5 * 60 * 1000; // 5 minutes
15
17
  class SharedSessionState {
18
+ sessionId;
19
+ instanceId;
20
+ cache;
21
+ cacheTTL;
22
+ store;
16
23
  constructor(store, sessionId, instanceId, opts) {
17
24
  this.sessionId = sessionId;
18
25
  this.instanceId = instanceId;
@@ -143,6 +150,9 @@ class SharedSessionState {
143
150
  }
144
151
  }
145
152
  class SessionStateStore extends SharedStateStore {
153
+ // Referenced (as `undefined`) by clearLeaderCache in the original JS; kept
154
+ // as an optional field to preserve behavior without introducing a value.
155
+ instanceId;
146
156
  constructor(opts) {
147
157
  super("session", opts, {
148
158
  mediaSeq: 0,
@@ -1,25 +1 @@
1
- export = SharedStateStore;
2
- declare class SharedStateStore {
3
- constructor(type: any, opts: any, initData: any);
4
- initData: any;
5
- type: any;
6
- cache: {};
7
- cacheTTL: any;
8
- shared: boolean;
9
- hasPipeline: boolean;
10
- store: MemcachedStateStore | MemoryStateStore | RedisStateStore;
11
- isShared(): boolean;
12
- canPipeline(): boolean;
13
- init(id: any): Promise<void>;
14
- reset(id: any): Promise<void>;
15
- resetAll(): Promise<void>;
16
- get(id: any, key: any): Promise<any>;
17
- set(id: any, key: any, value: any): Promise<any>;
18
- setVolatile(id: any, key: any, value: any): Promise<any>;
19
- getValues(id: any, keys: any): Promise<{}>;
20
- setValues(id: any, data: any): Promise<{}>;
21
- remove(id: any, key: any): Promise<void>;
22
- }
23
- import MemcachedStateStore = require("./memcached_state_store.js");
24
- import MemoryStateStore = require("./memory_state_store.js");
25
- import RedisStateStore = require("./redis_state_store.js");
1
+ export {};
@@ -1,9 +1,19 @@
1
1
  "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
2
3
  const debug = require("debug")("engine-state-store");
3
4
  const RedisStateStore = require("./redis_state_store.js");
4
5
  const MemcachedStateStore = require("./memcached_state_store.js");
5
6
  const MemoryStateStore = require("./memory_state_store.js");
7
+ // Type-only migration (#373): a faithful port of the original JS. The public
8
+ // API (constructor + methods) and runtime behavior are unchanged.
6
9
  class SharedStateStore {
10
+ initData;
11
+ type;
12
+ cache;
13
+ cacheTTL;
14
+ shared;
15
+ hasPipeline;
16
+ store;
7
17
  constructor(type, opts, initData) {
8
18
  this.initData = initData;
9
19
  this.type = type;
@@ -0,0 +1,32 @@
1
+ /**
2
+ * The low-level key/value store contract implemented by the memory, memcached
3
+ * and redis backends and driven by `SharedStateStore`.
4
+ */
5
+ export interface IStateStore {
6
+ initAsync(id: string, initData: Record<string, any>): Promise<any>;
7
+ resetAsync(id: string, initData: Record<string, any>): Promise<void>;
8
+ resetAllAsync(): Promise<void>;
9
+ getAsync(id: string, key: string): Promise<any>;
10
+ setAsync(id: string, key: string, value: any): Promise<any>;
11
+ setVolatileAsync(id: string, key: string, value: any): Promise<any>;
12
+ removeAsync(id: string, key: string): Promise<any>;
13
+ getValues?(id: string, keys: string[]): Promise<Record<string, any>>;
14
+ setValues?(id: string, data: Record<string, any>): Promise<Record<string, any>>;
15
+ }
16
+ export type SharedStates = {
17
+ [id: string]: {
18
+ [key: string]: any;
19
+ } | null;
20
+ };
21
+ export interface ISharedStateStoreOpts {
22
+ cacheTTL?: number;
23
+ redisUrl?: string;
24
+ memcachedUrl?: string;
25
+ version?: string;
26
+ volatileKeyTTL?: number;
27
+ [key: string]: any;
28
+ }
29
+ export interface ILeaderCache {
30
+ ts: number;
31
+ value: string | null;
32
+ }
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ // Shared type definitions for the engine state-store layer (#373).
3
+ // Type-only declarations — no runtime code is emitted for this module beyond
4
+ // an empty object, and nothing here changes runtime behavior.
5
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,40 +1 @@
1
- export = StreamSwitcher;
2
- declare class StreamSwitcher {
3
- constructor(config: any);
4
- sessionId: any;
5
- useDemuxedAudio: boolean;
6
- cloudWatchLogging: boolean;
7
- streamTypeLive: boolean;
8
- streamSwitchManager: any;
9
- eventId: any;
10
- working: boolean;
11
- timeDiff: any;
12
- abortTimeStamp: number;
13
- prerollsCache: {};
14
- getEventId(): any;
15
- abortLiveFeed(session: any, sessionLive: any, message: any): Promise<boolean>;
16
- /**
17
- *
18
- * @param {Session} session The VOD2Live Session object.
19
- * @param {SessionLive} sessionLive The Live Session object.
20
- * @returns A bool, true if streamSwitchManager contains current Live event to be played else false.
21
- */
22
- streamSwitcher(session: Session, sessionLive: SessionLive): Promise<boolean>;
23
- _initSwitching(state: any, session: any, sessionLive: any, scheduleObj: any): Promise<boolean>;
24
- _isEmpty(obj: any): boolean;
25
- _validURI(uri: any): Promise<boolean>;
26
- _loadPreroll(uri: any): Promise<{
27
- mediaSegments: {};
28
- audioSegments: {};
29
- }>;
30
- _createCustomSimpleSegmentList(segmentList: any, manifestURI: any): {}[];
31
- _getGroupAndLangIdxFromIdx(idx: any, audioObject: any): {
32
- groupId: any;
33
- lang: any;
34
- };
35
- _fetchParseM3u8(uri: any): Promise<any>;
36
- _mergeSegments(fromSegments: any, toSegments: any, prepend: any): {};
37
- _mergeAudioSegments(fromSegments: any, toSegments: any, prepend: any): any;
38
- _insertTimedMetadata(segments: any, timedMetadata: any): void;
39
- _insertTimedMetadataAudio(segments: any, timedMetadata: any): void;
40
- }
1
+ export {};