@norskvideo/norsk-sdk 1.0.367 → 1.0.370
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/lib/package.json +46 -0
- package/lib/src/media_nodes/common.d.ts +24 -4
- package/lib/src/media_nodes/common.js +28 -2
- package/lib/src/media_nodes/input.d.ts +18 -3
- package/lib/src/media_nodes/input.js +1 -0
- package/lib/src/media_nodes/mediaStore.d.ts +16 -12
- package/lib/src/media_nodes/mediaStore.js +54 -9
- package/lib/src/media_nodes/output.d.ts +25 -0
- package/lib/src/media_nodes/output.js +12 -6
- package/lib/src/media_nodes/processor.d.ts +100 -11
- package/lib/src/media_nodes/processor.js +120 -1
- package/lib/src/media_nodes/types.d.ts +14 -2
- package/lib/src/media_nodes/types.js +50 -12
- package/lib/src/sdk.d.ts +5 -0
- package/lib/src/sdk.js +16 -4
- package/lib/src/types.d.ts +0 -3
- package/lib/src/types.js +2 -0
- package/package.json +2 -2
- package/src/sdk.ts +36 -11
- package/src/types.ts +23 -21
- package/tsconfig.json +3 -1
- package/dist/norsk-sdk.d.ts +0 -5826
- package/lib/src/tsdoc-metadata.json +0 -11
package/lib/package.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"license": "MIT",
|
|
3
|
+
"name": "@norskvideo/norsk-sdk",
|
|
4
|
+
"version": "1.0.370",
|
|
5
|
+
"dependencies": {
|
|
6
|
+
"@bufbuild/protobuf": "^0.3.0",
|
|
7
|
+
"@grpc/grpc-js": "^1.2.2",
|
|
8
|
+
"@norskvideo/norsk-api": "1.0.370",
|
|
9
|
+
"lodash": "^4.17.21",
|
|
10
|
+
"typescript-nullable": "^0.6.0"
|
|
11
|
+
},
|
|
12
|
+
"files": [
|
|
13
|
+
"dist/norsk-sdk.d.ts",
|
|
14
|
+
"lib/**/*.js",
|
|
15
|
+
"lib/**/*d.ts",
|
|
16
|
+
"lib/src/tsdoc-metadata.json",
|
|
17
|
+
"package.json",
|
|
18
|
+
"src/*.ts",
|
|
19
|
+
"tsconfig.json"
|
|
20
|
+
],
|
|
21
|
+
"scripts": {
|
|
22
|
+
"build": "npx tsc && npx eslint src",
|
|
23
|
+
"clean": "rm -rf lib",
|
|
24
|
+
"api-extractor": "rm -rf docs/gen/api-extractor && mkdir -p docs/gen/api-extractor/{temp,json,report} && npx api-extractor run --local --verbose",
|
|
25
|
+
"api-markdown": "npx api-documenter markdown --input-folder docs/gen/api-extractor/json --output-folder docs/gen/api-extractor/markdown"
|
|
26
|
+
},
|
|
27
|
+
"main": "./lib/src/sdk.js",
|
|
28
|
+
"types": "./lib/src/sdk.d.ts",
|
|
29
|
+
"exports": {
|
|
30
|
+
"types": "./lib/src/sdk.d.ts",
|
|
31
|
+
"import": "./lib/src/sdk.js",
|
|
32
|
+
"node": "./lib/src/sdk.js",
|
|
33
|
+
"require": "./lib/src/sdk.js",
|
|
34
|
+
"default": "./lib/src/sdk.js"
|
|
35
|
+
},
|
|
36
|
+
"prettier": {},
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"@microsoft/api-documenter": "^7.19.27",
|
|
39
|
+
"@microsoft/api-extractor": "^7.33.7",
|
|
40
|
+
"@typescript-eslint/eslint-plugin": "^6.2.0",
|
|
41
|
+
"@typescript-eslint/parser": "^6.2.0",
|
|
42
|
+
"eslint": "^8.46.0",
|
|
43
|
+
"@types/lodash": "^4.14.202",
|
|
44
|
+
"typescript": "^4.1.2"
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
1
2
|
import * as grpc from "@grpc/grpc-js";
|
|
2
3
|
import { MediaClient as MediaClientPB } from "@norskvideo/norsk-api/lib/media_grpc_pb";
|
|
4
|
+
import EventEmitter from "events";
|
|
5
|
+
/** @public */
|
|
3
6
|
export declare type MediaClient = {
|
|
4
7
|
media: MediaClientPB;
|
|
5
8
|
subscriptions: grpc.ClientDuplexStream<SubscriptionChannelMessage, SubscriptionChannelResponse>;
|
|
@@ -61,12 +64,23 @@ export interface StreamStatisticsMixin {
|
|
|
61
64
|
stats: MultiStreamStatistics) => void;
|
|
62
65
|
onGopStructure?: (structure: GopStructure) => void;
|
|
63
66
|
}
|
|
67
|
+
export declare type EventMap = {
|
|
68
|
+
[key: string]: (arg: any) => void;
|
|
69
|
+
};
|
|
70
|
+
export declare type MediaNodeStateEvents = {
|
|
71
|
+
close: (id: string) => void;
|
|
72
|
+
};
|
|
64
73
|
/** @public */
|
|
65
|
-
export declare class MediaNodeState {
|
|
74
|
+
export declare class MediaNodeState<Events extends EventMap & MediaNodeStateEvents = MediaNodeStateEvents> {
|
|
66
75
|
id: MediaNodeId | undefined;
|
|
67
76
|
closeAwait?: () => void;
|
|
68
77
|
closed: boolean;
|
|
78
|
+
events: EventEmitter;
|
|
79
|
+
protected emit<E extends (keyof Events) & string>(name: E, arg: Parameters<Events[E]>[0]): void;
|
|
80
|
+
on<E extends (keyof Events) & string>(name: E, listener: Events[E]): void;
|
|
81
|
+
off<E extends (keyof Events) & string>(name: E, listener: Events[E]): void;
|
|
69
82
|
constructor(client: MediaClient);
|
|
83
|
+
/** @public */
|
|
70
84
|
close(): Promise<void>;
|
|
71
85
|
}
|
|
72
86
|
/** @public */
|
|
@@ -81,12 +95,18 @@ export declare type ReceiveFromAddressAuto = {
|
|
|
81
95
|
};
|
|
82
96
|
/** @public */
|
|
83
97
|
export declare type PinToKey<Pins extends string> = Nullable<Partial<Record<Pins, StreamKey[]>>>;
|
|
98
|
+
/** @public */
|
|
84
99
|
export interface SubscribeDestination {
|
|
85
100
|
id?: string;
|
|
86
101
|
sourceContextChange(responseCallback: (error?: SubscriptionError) => void): Promise<boolean>;
|
|
102
|
+
on?: (e: "close", a: () => void) => void;
|
|
103
|
+
off?: (e: "close", a: () => void) => void;
|
|
87
104
|
}
|
|
105
|
+
export declare type SourceMediaNodeEvents = {
|
|
106
|
+
outboundContextChange: (streams: StreamMetadata[]) => void;
|
|
107
|
+
} & MediaNodeStateEvents;
|
|
88
108
|
/** @public */
|
|
89
|
-
export declare class SourceMediaNode extends MediaNodeState {
|
|
109
|
+
export declare class SourceMediaNode<Events extends SourceMediaNodeEvents = SourceMediaNodeEvents> extends MediaNodeState<Events> {
|
|
90
110
|
outputStreams: StreamMetadata[];
|
|
91
111
|
registerForContextChange(subscriber: SubscribeDestination): void;
|
|
92
112
|
unregisterForContextChange(subscriber: SubscribeDestination): void;
|
|
@@ -106,7 +126,7 @@ export declare class SourceMediaNode extends MediaNodeState {
|
|
|
106
126
|
* */
|
|
107
127
|
export declare type SubscriptionValidationResponse = true | false | "accept" | "deny" | "accept_and_terminate" | "deny_and_queue" | "deny_and_drop";
|
|
108
128
|
/** @public */
|
|
109
|
-
export declare class SinkMediaNode<Pins extends string> extends MediaNodeState implements SubscribeDestination {
|
|
129
|
+
export declare class SinkMediaNode<Pins extends string, Events extends MediaNodeStateEvents = MediaNodeStateEvents> extends MediaNodeState<Events> implements SubscribeDestination {
|
|
110
130
|
permissiveSubscriptionValidation(_context: Context): SubscriptionValidationResponse;
|
|
111
131
|
restrictiveSubscriptionValidation(context: Context): SubscriptionValidationResponse;
|
|
112
132
|
/** Subscribe to the given sources.
|
|
@@ -129,7 +149,7 @@ export declare class SinkMediaNode<Pins extends string> extends MediaNodeState i
|
|
|
129
149
|
finalise(): void;
|
|
130
150
|
}
|
|
131
151
|
/** @public */
|
|
132
|
-
export declare class AutoSinkMediaNode<Pins extends string> extends SinkMediaNode<Pins | "auto"> {
|
|
152
|
+
export declare class AutoSinkMediaNode<Pins extends string, Events extends MediaNodeStateEvents = MediaNodeStateEvents> extends SinkMediaNode<Pins | "auto", Events> {
|
|
133
153
|
/** Subscribe to the given sources.
|
|
134
154
|
*
|
|
135
155
|
* This version of subscribe simply requires a list of stream keys to be
|
|
@@ -13,8 +13,12 @@ var __createBinding = (this && this.__createBinding) || (Object.create ? (functi
|
|
|
13
13
|
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
17
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
18
|
+
};
|
|
16
19
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
20
|
exports.registerStreamHandlers = exports._ackContext = exports.AutoSinkMediaNode = exports.SinkMediaNode = exports.SourceMediaNode = exports.MediaNodeState = exports.applyMixins = void 0;
|
|
21
|
+
const events_1 = __importDefault(require("events"));
|
|
18
22
|
const media_pb_1 = require("@norskvideo/norsk-api/lib/media_pb");
|
|
19
23
|
const constants_1 = require("@grpc/grpc-js/build/src/constants");
|
|
20
24
|
const typescript_nullable_1 = require("typescript-nullable");
|
|
@@ -43,9 +47,20 @@ exports.applyMixins = applyMixins;
|
|
|
43
47
|
class MediaNodeState {
|
|
44
48
|
constructor(client) {
|
|
45
49
|
this.closed = false;
|
|
50
|
+
this.events = new events_1.default();
|
|
46
51
|
this.client = client;
|
|
47
52
|
this.id = undefined;
|
|
48
53
|
}
|
|
54
|
+
emit(name, arg) {
|
|
55
|
+
this.events.emit(name, arg);
|
|
56
|
+
}
|
|
57
|
+
on(name, listener) {
|
|
58
|
+
this.events.on(name, listener);
|
|
59
|
+
}
|
|
60
|
+
off(name, listener) {
|
|
61
|
+
this.events.off(name, listener);
|
|
62
|
+
}
|
|
63
|
+
/** @public */
|
|
49
64
|
async close() {
|
|
50
65
|
if (this.closed)
|
|
51
66
|
return;
|
|
@@ -54,6 +69,8 @@ class MediaNodeState {
|
|
|
54
69
|
(0, utils_1.debuglog)("Sending close request for media node with id %s", this.id);
|
|
55
70
|
this.closeAwait = r;
|
|
56
71
|
this.client.media.closeMediaNode((0, utils_1.provideFull)(media_pb_1.MediaNodeId, { id: this.id }), () => { });
|
|
72
|
+
this.emit('close', this.id);
|
|
73
|
+
this.events.removeAllListeners();
|
|
57
74
|
}
|
|
58
75
|
else
|
|
59
76
|
r();
|
|
@@ -82,9 +99,16 @@ class SourceMediaNode extends MediaNodeState {
|
|
|
82
99
|
this.onOutboundContextChange = onOutboundContextChange;
|
|
83
100
|
}
|
|
84
101
|
registerForContextChange(subscriber) {
|
|
85
|
-
|
|
102
|
+
const closeCb = () => {
|
|
103
|
+
this.subscribers.delete(subscriber);
|
|
104
|
+
};
|
|
105
|
+
subscriber.on?.('close', closeCb);
|
|
106
|
+
this.subscribers.set(subscriber, closeCb);
|
|
86
107
|
}
|
|
87
108
|
unregisterForContextChange(subscriber) {
|
|
109
|
+
const closeCb = this.subscribers.get(subscriber);
|
|
110
|
+
if (closeCb)
|
|
111
|
+
subscriber.off?.('close', closeCb);
|
|
88
112
|
this.subscribers.delete(subscriber);
|
|
89
113
|
}
|
|
90
114
|
/** @internal */
|
|
@@ -131,6 +155,8 @@ class SourceMediaNode extends MediaNodeState {
|
|
|
131
155
|
if (this.onOutboundContextChange) {
|
|
132
156
|
await this.onOutboundContextChange(this.outputStreams);
|
|
133
157
|
}
|
|
158
|
+
// And some people might just want to know about it without blocking
|
|
159
|
+
this.emit('outboundContextChange', this.outputStreams);
|
|
134
160
|
const pending = { pendingSubscribes: [], readyToAck: false };
|
|
135
161
|
this.pendingContextAcks.set(context.blockingCallRef, pending);
|
|
136
162
|
const notifications = [];
|
|
@@ -419,7 +445,7 @@ function registerStreamHandlers(grpcStream, unregisterNode, tag, reject, setting
|
|
|
419
445
|
if (settings.onError) {
|
|
420
446
|
return;
|
|
421
447
|
}
|
|
422
|
-
|
|
448
|
+
(0, utils_1.errorlog)("Error:", source, err.code, constants_1.Status[err.code], err.details, err.metadata?.getMap());
|
|
423
449
|
};
|
|
424
450
|
grpcStream.on("end", () => {
|
|
425
451
|
(0, utils_1.debuglog)(`End of ${tag} node`);
|
|
@@ -357,6 +357,10 @@ export interface LocalFileInputSettings extends InputSettings<SourceMediaNode> {
|
|
|
357
357
|
/** An optional callback that will be invoked when file end is reached */
|
|
358
358
|
onEof?: () => void;
|
|
359
359
|
}
|
|
360
|
+
/**
|
|
361
|
+
* @public
|
|
362
|
+
* see: {@link NorskInput.fileWebVtt}
|
|
363
|
+
*/
|
|
360
364
|
export interface WebVttFileInputSettings extends LocalFileInputSettings {
|
|
361
365
|
/** Language tag to associate with the stream (optional) */
|
|
362
366
|
language?: string;
|
|
@@ -369,6 +373,10 @@ export interface WebVttFileInputSettings extends LocalFileInputSettings {
|
|
|
369
373
|
*/
|
|
370
374
|
export declare class FileWebVttInputNode extends SourceMediaNode {
|
|
371
375
|
}
|
|
376
|
+
/**
|
|
377
|
+
* @public
|
|
378
|
+
* see: {@link NorskInput.streamWebVtt}
|
|
379
|
+
*/
|
|
372
380
|
export interface StreamWebVttInputSettings extends InputSettings<StreamWebVttInputNode> {
|
|
373
381
|
/** Language tag to associate with the stream (optional) */
|
|
374
382
|
language?: string;
|
|
@@ -523,10 +531,12 @@ export interface UdpTsInputSettings extends RemoteInputSettings<UdpTsInputNode>
|
|
|
523
531
|
*/
|
|
524
532
|
export declare class UdpTsInputNode extends TsCommonInputNode<UdpTsInputMessage, UdpTsInputNode> {
|
|
525
533
|
}
|
|
534
|
+
/** @public */
|
|
526
535
|
export interface M3u8MediaInputSettings extends InputSettings<M3u8InputNode> {
|
|
527
536
|
url: string;
|
|
528
537
|
}
|
|
529
538
|
/**
|
|
539
|
+
* @public
|
|
530
540
|
* see: {@link NorskInput.m3u8Media}
|
|
531
541
|
*/
|
|
532
542
|
export declare class M3u8InputNode extends TsCommonInputNode<M3u8MediaInputMessage, M3u8InputNode> {
|
|
@@ -616,7 +626,7 @@ export declare class AudioSignalGeneratorNode extends SourceMediaNode {
|
|
|
616
626
|
/**
|
|
617
627
|
* @public
|
|
618
628
|
* Settings for an Video Testcard Generator
|
|
619
|
-
* see: {@link NorskInput.
|
|
629
|
+
* see: {@link NorskInput.videoTestCard}
|
|
620
630
|
* */
|
|
621
631
|
export interface VideoTestcardGeneratorSettings extends SourceNodeSettings<VideoTestcardGeneratorNode> {
|
|
622
632
|
/** The source name to set in the stream key of the outgoing stream */
|
|
@@ -687,6 +697,11 @@ export interface FileMp4InputSettings extends SourceNodeSettings<FileMp4InputNod
|
|
|
687
697
|
/** Whether to start paused or already playing (default: playing) */
|
|
688
698
|
start?: 'playing' | 'paused';
|
|
689
699
|
}
|
|
700
|
+
/**
|
|
701
|
+
* @public
|
|
702
|
+
* Settings for updating a file-based Mp4 Input
|
|
703
|
+
* see: {@link FileMp4InputNode.updateSettings}
|
|
704
|
+
*/
|
|
690
705
|
export interface FileMp4InputSettingsUpdate {
|
|
691
706
|
/** Whether to loop back to the start of the file after reaching the end */
|
|
692
707
|
loop?: boolean;
|
|
@@ -762,13 +777,13 @@ export interface NorskInput {
|
|
|
762
777
|
udpTs(settings: UdpTsInputSettings): Promise<UdpTsInputNode>;
|
|
763
778
|
/**
|
|
764
779
|
* Read subtitles from a WebVTT file on disk
|
|
765
|
-
* @param settings
|
|
780
|
+
* @param settings - Configuration for the file input
|
|
766
781
|
*/
|
|
767
782
|
fileWebVtt(settings: WebVttFileInputSettings): Promise<FileWebVttInputNode>;
|
|
768
783
|
/**
|
|
769
784
|
* Stream subtitles in WebVTT format via API calls. Chunks of WebVTT cues can be sent
|
|
770
785
|
* in an ongoing timeline (as if streaming a fragmented WebVTT file)
|
|
771
|
-
* @param settings
|
|
786
|
+
* @param settings - Configuration for the stream input
|
|
772
787
|
*/
|
|
773
788
|
streamWebVtt(settings: StreamWebVttInputSettings): Promise<StreamWebVttInputNode>;
|
|
774
789
|
/**
|
|
@@ -99,7 +99,7 @@ declare type MediaStoreCut = {
|
|
|
99
99
|
/**
|
|
100
100
|
* @public
|
|
101
101
|
* Settings to configure a media store recorder
|
|
102
|
-
* see {@link
|
|
102
|
+
* see {@link NorskMediaStore.recorder}
|
|
103
103
|
*/
|
|
104
104
|
export interface MediaStoreRecorderSettings extends SinkNodeSettings<MediaStoreRecorderNode>, StreamStatisticsMixin {
|
|
105
105
|
/**
|
|
@@ -121,7 +121,7 @@ export interface MediaStoreRecorderSettings extends SinkNodeSettings<MediaStoreR
|
|
|
121
121
|
}
|
|
122
122
|
/**
|
|
123
123
|
* @public
|
|
124
|
-
* see: {@link
|
|
124
|
+
* see: {@link NorskMediaStore.recorder}
|
|
125
125
|
*/
|
|
126
126
|
export declare class MediaStoreRecorderNode extends AutoSinkMediaNode<"audio" | "video"> {
|
|
127
127
|
metadata(): Promise<MediaStoreSession[]>;
|
|
@@ -130,7 +130,7 @@ export declare class MediaStoreRecorderNode extends AutoSinkMediaNode<"audio" |
|
|
|
130
130
|
/**
|
|
131
131
|
* @public
|
|
132
132
|
* Settings for Media Store playback
|
|
133
|
-
* see: {@link
|
|
133
|
+
* see: {@link NorskMediaStore.player}
|
|
134
134
|
*/
|
|
135
135
|
export interface MediaStorePlayerSettings extends InputSettings<MediaStorePlayerNode>, StreamStatisticsMixin {
|
|
136
136
|
/**
|
|
@@ -142,13 +142,13 @@ export interface MediaStorePlayerSettings extends InputSettings<MediaStorePlayer
|
|
|
142
142
|
}
|
|
143
143
|
/**
|
|
144
144
|
* @public
|
|
145
|
-
* see: {@link
|
|
145
|
+
* see: {@link NorskMediaStore.player}
|
|
146
146
|
*/
|
|
147
147
|
export declare class MediaStorePlayerNode extends SourceMediaNode {
|
|
148
148
|
}
|
|
149
149
|
/**
|
|
150
150
|
* @public
|
|
151
|
-
* see: {@link
|
|
151
|
+
* see: {@link NorskMediaStore.makeCut}
|
|
152
152
|
*/
|
|
153
153
|
export declare class MediaStoreActiveCut {
|
|
154
154
|
/**
|
|
@@ -162,12 +162,12 @@ export declare class MediaStoreActiveCut {
|
|
|
162
162
|
export declare type MediaStoreAssetFileWithHash = {
|
|
163
163
|
file: string;
|
|
164
164
|
hash: string;
|
|
165
|
-
|
|
165
|
+
importIfNeeded?: boolean;
|
|
166
166
|
};
|
|
167
167
|
/** @public */
|
|
168
168
|
export declare type MediaStoreAssetFile = {
|
|
169
169
|
file: string;
|
|
170
|
-
|
|
170
|
+
importIfNeeded?: boolean;
|
|
171
171
|
};
|
|
172
172
|
/** @public */
|
|
173
173
|
export declare type MediaStoreAssetSource = MediaStoreAssetFileWithHash | MediaStoreAssetFile;
|
|
@@ -180,19 +180,22 @@ export declare type MediaStoreAssetSettings = {
|
|
|
180
180
|
};
|
|
181
181
|
/**
|
|
182
182
|
* @public
|
|
183
|
-
* see: {@link
|
|
183
|
+
* see: {@link NorskMediaStore.asyncLoadAsset}
|
|
184
184
|
*/
|
|
185
185
|
export declare class MediaStoreAsset {
|
|
186
186
|
/** @public */
|
|
187
187
|
durationMs?: bigint;
|
|
188
188
|
/** @public */
|
|
189
189
|
size?: bigint;
|
|
190
|
+
/** @public */
|
|
191
|
+
metadata?: MediaStoreSession[];
|
|
190
192
|
cutListEntry(settings: MediaStoreAssetCut): MediaStoreCut;
|
|
193
|
+
close(): void;
|
|
191
194
|
}
|
|
192
195
|
/**
|
|
193
196
|
* @public
|
|
194
197
|
* Settings to configure a media store snapshot
|
|
195
|
-
* see {@link
|
|
198
|
+
* see {@link NorskMediaStore.snapshot}
|
|
196
199
|
*/
|
|
197
200
|
export interface MediaStoreSnapshotSettings {
|
|
198
201
|
/**
|
|
@@ -206,16 +209,17 @@ export interface MediaStoreSnapshotSettings {
|
|
|
206
209
|
}
|
|
207
210
|
/**
|
|
208
211
|
* @public
|
|
209
|
-
* see: {@link
|
|
212
|
+
* see: {@link NorskMediaStore.snapshot}
|
|
210
213
|
*/
|
|
211
214
|
export declare class MediaStoreSnapshot {
|
|
212
215
|
update(): Promise<void>;
|
|
213
216
|
metadata(): Promise<MediaStoreSession[]>;
|
|
214
217
|
cutListEntry(settings: MediaStoreRecorderCut): MediaStoreCut;
|
|
218
|
+
close(): void;
|
|
215
219
|
}
|
|
216
220
|
/**
|
|
217
221
|
* @public
|
|
218
|
-
* Methods
|
|
222
|
+
* Methods to interact with the Media Store live-to-vod recording engine
|
|
219
223
|
*/
|
|
220
224
|
export interface NorskMediaStore {
|
|
221
225
|
/**
|
|
@@ -231,7 +235,7 @@ export interface NorskMediaStore {
|
|
|
231
235
|
/**
|
|
232
236
|
* Create a media store cut
|
|
233
237
|
*
|
|
234
|
-
* @param
|
|
238
|
+
* @param request - Configuration for the cut
|
|
235
239
|
*/
|
|
236
240
|
makeCut(request: MediaStoreCutRequest): MediaStoreActiveCut;
|
|
237
241
|
/**
|
|
@@ -89,7 +89,7 @@ function toSingleCuts(cuts) {
|
|
|
89
89
|
}
|
|
90
90
|
/**
|
|
91
91
|
* @public
|
|
92
|
-
* see: {@link
|
|
92
|
+
* see: {@link NorskMediaStore.recorder}
|
|
93
93
|
*/
|
|
94
94
|
class MediaStoreRecorderNode extends common_1.AutoSinkMediaNode {
|
|
95
95
|
/** @internal */
|
|
@@ -154,6 +154,8 @@ class MediaStoreRecorderNode extends common_1.AutoSinkMediaNode {
|
|
|
154
154
|
return node.initialised;
|
|
155
155
|
}
|
|
156
156
|
async metadata() {
|
|
157
|
+
if (this.closed)
|
|
158
|
+
throw new Error("Store Closed");
|
|
157
159
|
const fn = util
|
|
158
160
|
.promisify(this.client.media.mediaStoreMetadata)
|
|
159
161
|
.bind(this.client.media);
|
|
@@ -161,6 +163,8 @@ class MediaStoreRecorderNode extends common_1.AutoSinkMediaNode {
|
|
|
161
163
|
.then(fromMediaStoreMetadataResponse);
|
|
162
164
|
}
|
|
163
165
|
cutListEntry(settings) {
|
|
166
|
+
if (this.closed)
|
|
167
|
+
throw new Error("Store Closed");
|
|
164
168
|
return {
|
|
165
169
|
mediaStoreName: this.settings.name,
|
|
166
170
|
cut: { type: "recorder", cut: settings }
|
|
@@ -170,7 +174,7 @@ class MediaStoreRecorderNode extends common_1.AutoSinkMediaNode {
|
|
|
170
174
|
exports.MediaStoreRecorderNode = MediaStoreRecorderNode;
|
|
171
175
|
/**
|
|
172
176
|
* @public
|
|
173
|
-
* see: {@link
|
|
177
|
+
* see: {@link NorskMediaStore.player}
|
|
174
178
|
*/
|
|
175
179
|
class MediaStorePlayerNode extends common_1.SourceMediaNode {
|
|
176
180
|
/** @internal */
|
|
@@ -223,7 +227,7 @@ class MediaStorePlayerNode extends common_1.SourceMediaNode {
|
|
|
223
227
|
exports.MediaStorePlayerNode = MediaStorePlayerNode;
|
|
224
228
|
/**
|
|
225
229
|
* @public
|
|
226
|
-
* see: {@link
|
|
230
|
+
* see: {@link NorskMediaStore.makeCut}
|
|
227
231
|
*/
|
|
228
232
|
class MediaStoreActiveCut {
|
|
229
233
|
/** @internal */
|
|
@@ -242,7 +246,10 @@ class MediaStoreActiveCut {
|
|
|
242
246
|
this.grpcStream = this.client.media.createMediaStoreCut();
|
|
243
247
|
this._isComplete = false;
|
|
244
248
|
this._complete = new Promise((resolve, reject) => {
|
|
245
|
-
this.grpcStream.on("error", (err) => {
|
|
249
|
+
this.grpcStream.on("error", (err) => {
|
|
250
|
+
this.grpcStream.destroy();
|
|
251
|
+
reject(err);
|
|
252
|
+
});
|
|
246
253
|
this.grpcStream.on("data", (data) => {
|
|
247
254
|
const messageCase = data.message.case;
|
|
248
255
|
switch (messageCase) {
|
|
@@ -254,11 +261,13 @@ class MediaStoreActiveCut {
|
|
|
254
261
|
}
|
|
255
262
|
case "cutCancelled": {
|
|
256
263
|
this._isComplete = true;
|
|
264
|
+
this.grpcStream.end();
|
|
257
265
|
reject(new Error("cancelled"));
|
|
258
266
|
break;
|
|
259
267
|
}
|
|
260
268
|
case "cutComplete": {
|
|
261
269
|
this._isComplete = true;
|
|
270
|
+
this.grpcStream.end();
|
|
262
271
|
resolve(data.message.value.size);
|
|
263
272
|
break;
|
|
264
273
|
}
|
|
@@ -298,11 +307,13 @@ function isMediaStoreAssetFileWithHash(asset) {
|
|
|
298
307
|
}
|
|
299
308
|
/**
|
|
300
309
|
* @public
|
|
301
|
-
* see: {@link
|
|
310
|
+
* see: {@link NorskMediaStore.asyncLoadAsset}
|
|
302
311
|
*/
|
|
303
312
|
class MediaStoreAsset {
|
|
304
313
|
/** @internal */
|
|
305
314
|
constructor(settings, client) {
|
|
315
|
+
/** @internal */
|
|
316
|
+
this.closed = false;
|
|
306
317
|
this.client = client;
|
|
307
318
|
this.settings = settings;
|
|
308
319
|
this.grpcStream = this.client.media.createMediaStoreAsset((0, common_1.provideFull)(media_pb_1.MediaStoreAssetSettings, {
|
|
@@ -313,19 +324,21 @@ class MediaStoreAsset {
|
|
|
313
324
|
fileWithHash: (0, common_1.provideFull)(media_pb_1.MediaStoreAssetFileWithHash, {
|
|
314
325
|
file: settings.source.file,
|
|
315
326
|
hash: settings.source.hash,
|
|
316
|
-
|
|
327
|
+
importIfNeeded: settings.source.importIfNeeded ?? true
|
|
317
328
|
})
|
|
318
329
|
}) :
|
|
319
330
|
(0, common_1.mkMessageCase)({
|
|
320
331
|
file: (0, common_1.provideFull)(media_pb_1.MediaStoreAssetFile, {
|
|
321
332
|
file: settings.source.file,
|
|
322
|
-
|
|
333
|
+
importIfNeeded: settings.source.importIfNeeded ?? true
|
|
323
334
|
})
|
|
324
335
|
})) : (0, common_1.mkMessageCase)({ noLoad: (0, common_1.provideFull)(protobuf_1.Empty, {}) })),
|
|
325
336
|
path: settings.path
|
|
326
337
|
}));
|
|
327
338
|
this._ready = new Promise((resolve, reject) => {
|
|
328
339
|
this.grpcStream.on("error", (err) => reject(err));
|
|
340
|
+
this.grpcStream.on("close", () => console.log("CLOSE"));
|
|
341
|
+
this.grpcStream.on("end", () => console.log("END"));
|
|
329
342
|
this.grpcStream.on("data", (data) => {
|
|
330
343
|
const messageCase = data.message.case;
|
|
331
344
|
switch (messageCase) {
|
|
@@ -338,7 +351,16 @@ class MediaStoreAsset {
|
|
|
338
351
|
case "importComplete": {
|
|
339
352
|
this.durationMs = data.message.value.durationMs;
|
|
340
353
|
this.size = data.message.value.size;
|
|
341
|
-
|
|
354
|
+
const metadataFn = util
|
|
355
|
+
.promisify(this.client.media.mediaStoreMetadata)
|
|
356
|
+
.bind(this.client.media);
|
|
357
|
+
metadataFn((0, common_1.provideFull)(media_pb_1.MediaStoreMetadataRequest, { mediaStoreName: this.settings.name }))
|
|
358
|
+
.then(fromMediaStoreMetadataResponse)
|
|
359
|
+
.then((metadata) => {
|
|
360
|
+
this.metadata = metadata;
|
|
361
|
+
resolve(this);
|
|
362
|
+
})
|
|
363
|
+
.catch((err) => reject(err));
|
|
342
364
|
break;
|
|
343
365
|
}
|
|
344
366
|
default:
|
|
@@ -353,6 +375,8 @@ class MediaStoreAsset {
|
|
|
353
375
|
return asset._ready;
|
|
354
376
|
}
|
|
355
377
|
cutListEntry(settings) {
|
|
378
|
+
if (this.closed)
|
|
379
|
+
throw new Error("Store Closed");
|
|
356
380
|
if (this.durationMs == null) {
|
|
357
381
|
throw new Error("Attempt to cut from an asset that isn't yet loaded");
|
|
358
382
|
}
|
|
@@ -365,15 +389,24 @@ class MediaStoreAsset {
|
|
|
365
389
|
cut: { type: "asset", cut: settings }
|
|
366
390
|
};
|
|
367
391
|
}
|
|
392
|
+
close() {
|
|
393
|
+
if (this.closed)
|
|
394
|
+
return;
|
|
395
|
+
this.grpcStream.cancel();
|
|
396
|
+
// this.grpcStream.destroy();
|
|
397
|
+
this.closed = true;
|
|
398
|
+
}
|
|
368
399
|
}
|
|
369
400
|
exports.MediaStoreAsset = MediaStoreAsset;
|
|
370
401
|
/**
|
|
371
402
|
* @public
|
|
372
|
-
* see: {@link
|
|
403
|
+
* see: {@link NorskMediaStore.snapshot}
|
|
373
404
|
*/
|
|
374
405
|
class MediaStoreSnapshot {
|
|
375
406
|
/** @internal */
|
|
376
407
|
constructor(settings, client) {
|
|
408
|
+
/** @internal */
|
|
409
|
+
this.closed = false;
|
|
377
410
|
this.client = client;
|
|
378
411
|
this.settings = settings;
|
|
379
412
|
this.grpcStream = this.client.media.createMediaStoreSnapshot();
|
|
@@ -413,6 +446,8 @@ class MediaStoreSnapshot {
|
|
|
413
446
|
return snapshot._ready;
|
|
414
447
|
}
|
|
415
448
|
async update() {
|
|
449
|
+
if (this.closed)
|
|
450
|
+
throw new Error("Store Closed");
|
|
416
451
|
if (this._updated) {
|
|
417
452
|
return new Promise((_resolve, reject) => { reject(new Error("Update in progress")); });
|
|
418
453
|
}
|
|
@@ -420,6 +455,8 @@ class MediaStoreSnapshot {
|
|
|
420
455
|
return new Promise((resolve, reject) => { this._updated = { resolve, reject }; });
|
|
421
456
|
}
|
|
422
457
|
async metadata() {
|
|
458
|
+
if (this.closed)
|
|
459
|
+
throw new Error("Store Closed");
|
|
423
460
|
const fn = util
|
|
424
461
|
.promisify(this.client.media.mediaStoreMetadata)
|
|
425
462
|
.bind(this.client.media);
|
|
@@ -427,11 +464,19 @@ class MediaStoreSnapshot {
|
|
|
427
464
|
.then(fromMediaStoreMetadataResponse);
|
|
428
465
|
}
|
|
429
466
|
cutListEntry(settings) {
|
|
467
|
+
if (this.closed)
|
|
468
|
+
throw new Error("Store Closed");
|
|
430
469
|
return {
|
|
431
470
|
mediaStoreName: this.settings.name,
|
|
432
471
|
cut: { type: "recorder", cut: settings }
|
|
433
472
|
};
|
|
434
473
|
}
|
|
474
|
+
close() {
|
|
475
|
+
if (this.closed)
|
|
476
|
+
return;
|
|
477
|
+
this.grpcStream.destroy();
|
|
478
|
+
this.closed = true;
|
|
479
|
+
}
|
|
435
480
|
}
|
|
436
481
|
exports.MediaStoreSnapshot = MediaStoreSnapshot;
|
|
437
482
|
/** @internal */
|
|
@@ -43,6 +43,11 @@ export interface CmafOutputSettings extends SinkNodeSettings<CmafAudioOutputNode
|
|
|
43
43
|
* The name to use for the playlist in a multivariant playlist
|
|
44
44
|
*/
|
|
45
45
|
name?: string;
|
|
46
|
+
/**
|
|
47
|
+
* Whether to insert a program date-time directive on every segment. Not required to produce spec-compliant playlists,
|
|
48
|
+
* but may be useful for inspection or playlist manipulation
|
|
49
|
+
*/
|
|
50
|
+
pdtEverySegment?: boolean;
|
|
46
51
|
}
|
|
47
52
|
/**
|
|
48
53
|
* @public
|
|
@@ -75,6 +80,11 @@ export interface HlsTsVideoOutputSettings extends SinkNodeSettings<HlsTsVideoOut
|
|
|
75
80
|
* The name to use for the playlist in a multivariant playlist
|
|
76
81
|
*/
|
|
77
82
|
name?: string;
|
|
83
|
+
/**
|
|
84
|
+
* Whether to insert a program date-time directive on every segment. Not required to produce spec-compliant playlists,
|
|
85
|
+
* but may be useful for inspection or playlist manipulation
|
|
86
|
+
*/
|
|
87
|
+
pdtEverySegment?: boolean;
|
|
78
88
|
}
|
|
79
89
|
/**
|
|
80
90
|
* @public
|
|
@@ -107,6 +117,11 @@ export interface HlsTsAudioOutputSettings extends SinkNodeSettings<HlsTsAudioOut
|
|
|
107
117
|
* The name to use for the playlist in a multivariant playlist
|
|
108
118
|
*/
|
|
109
119
|
name?: string;
|
|
120
|
+
/**
|
|
121
|
+
* Whether to insert a program date-time directive on every segment. Not required to produce spec-compliant playlists,
|
|
122
|
+
* but may be useful for inspection or playlist manipulation
|
|
123
|
+
*/
|
|
124
|
+
pdtEverySegment?: boolean;
|
|
110
125
|
}
|
|
111
126
|
/**
|
|
112
127
|
* @public
|
|
@@ -127,6 +142,11 @@ export interface CmafWebVttOutputSettings extends SinkNodeSettings<CmafWebVttOut
|
|
|
127
142
|
* The name to use for the playlist in a multivariant playlist
|
|
128
143
|
*/
|
|
129
144
|
name?: string;
|
|
145
|
+
/**
|
|
146
|
+
* Whether to insert a program date-time directive on every segment. Not required to produce spec-compliant playlists,
|
|
147
|
+
* but may be useful for inspection or playlist manipulation
|
|
148
|
+
*/
|
|
149
|
+
pdtEverySegment?: boolean;
|
|
130
150
|
}
|
|
131
151
|
/**
|
|
132
152
|
* @public
|
|
@@ -170,6 +190,11 @@ export interface HlsTsCombinedPushOutputSettings extends SinkNodeSettings<HlsTsC
|
|
|
170
190
|
* The name to use for the playlist in a multivariant playlist
|
|
171
191
|
*/
|
|
172
192
|
name?: string;
|
|
193
|
+
/**
|
|
194
|
+
* Whether to insert a program date-time directive on every segment. Not required to produce spec-compliant playlists,
|
|
195
|
+
* but may be useful for inspection or playlist manipulation
|
|
196
|
+
*/
|
|
197
|
+
pdtEverySegment?: boolean;
|
|
173
198
|
}
|
|
174
199
|
/**
|
|
175
200
|
* @public
|