@norskvideo/norsk-sdk 1.0.357 → 1.0.358
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/src/media_nodes/common.js +114 -141
- package/lib/src/media_nodes/debug.js +5 -18
- package/lib/src/media_nodes/input.js +141 -154
- package/lib/src/media_nodes/output.d.ts +27 -4
- package/lib/src/media_nodes/output.js +337 -255
- package/lib/src/media_nodes/processor.d.ts +63 -3
- package/lib/src/media_nodes/processor.js +367 -358
- package/lib/src/media_nodes/types.d.ts +4 -4
- package/lib/src/media_nodes/types.js +82 -52
- package/lib/src/sdk.d.ts +8 -1
- package/lib/src/sdk.js +96 -100
- package/lib/src/system.js +9 -20
- package/lib/src/types.js +1 -1
- package/package.json +2 -2
- package/src/sdk.ts +25 -3
- package/tsconfig.json +1 -1
|
@@ -25,15 +25,6 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
25
25
|
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
26
26
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
27
27
|
};
|
|
28
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
29
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
30
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
31
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
32
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
33
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
34
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
35
|
-
});
|
|
36
|
-
};
|
|
37
28
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
38
29
|
exports.registerStreamHandlers = exports.AutoSinkMediaNode = exports.SinkMediaNode = exports.SourceMediaNode = exports.MediaNodeState = exports.applyMixins = void 0;
|
|
39
30
|
const media_pb_1 = require("@norskvideo/norsk-api/lib/media_pb");
|
|
@@ -68,19 +59,17 @@ class MediaNodeState {
|
|
|
68
59
|
this.client = client;
|
|
69
60
|
this.id = undefined;
|
|
70
61
|
}
|
|
71
|
-
close() {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
r();
|
|
83
|
-
}));
|
|
62
|
+
async close() {
|
|
63
|
+
if (this.closed)
|
|
64
|
+
return;
|
|
65
|
+
return new Promise(async (r) => {
|
|
66
|
+
if (this.id) {
|
|
67
|
+
(0, utils_1.debuglog)("Sending close request for media node with id %s", this.id);
|
|
68
|
+
this.closeAwait = r;
|
|
69
|
+
this.client.closeMediaNode((0, utils_1.provideFull)(media_pb_1.MediaNodeId, { id: this.id }), () => { });
|
|
70
|
+
}
|
|
71
|
+
else
|
|
72
|
+
r();
|
|
84
73
|
});
|
|
85
74
|
}
|
|
86
75
|
/** @internal */
|
|
@@ -149,31 +138,29 @@ class SourceMediaNode extends MediaNodeState {
|
|
|
149
138
|
}
|
|
150
139
|
}
|
|
151
140
|
/** @internal */
|
|
152
|
-
outboundContextChange(context) {
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
141
|
+
async outboundContextChange(context) {
|
|
142
|
+
(0, utils_1.debuglog)("Node '%s' received new outbound context %O", this.id, debugFormatContext(context));
|
|
143
|
+
this.outputStreams = context.streams.map(types_1.fromStreamMetadata);
|
|
144
|
+
// The client can do something before we notify subscribers then unblock - e.g. maybe spinning up a new node and subscribing it
|
|
145
|
+
if (this.onOutboundContextChange) {
|
|
146
|
+
await this.onOutboundContextChange(this.outputStreams);
|
|
147
|
+
}
|
|
148
|
+
let pending = { pendingSubscribes: [], readyToAck: false };
|
|
149
|
+
this.pendingContextAcks.set(context.blockingCallRef, pending);
|
|
150
|
+
for (let [subscriber, _] of this.subscribers) {
|
|
151
|
+
// Okay, this is async
|
|
152
|
+
// which means that while one is executing, another can complete
|
|
153
|
+
// and that just messes the whole world up beause we haven't stashed it away yet!
|
|
154
|
+
const alive = await subscriber.sourceContextChange(this.subscriptionComplete(context, subscriber));
|
|
155
|
+
if (alive) {
|
|
156
|
+
pending.pendingSubscribes.push(subscriber);
|
|
159
157
|
}
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
for (let [subscriber, _] of this.subscribers) {
|
|
163
|
-
// Okay, this is async
|
|
164
|
-
// which means that while one is executing, another can complete
|
|
165
|
-
// and that just messes the whole world up beause we haven't stashed it away yet!
|
|
166
|
-
const alive = yield subscriber.sourceContextChange(this.subscriptionComplete(context, subscriber));
|
|
167
|
-
if (alive) {
|
|
168
|
-
pending.pendingSubscribes.push(subscriber);
|
|
169
|
-
}
|
|
170
|
-
else {
|
|
171
|
-
(0, utils_1.debuglog)("Skipping updating subscription to closed node %s", subscriber.id);
|
|
172
|
-
}
|
|
158
|
+
else {
|
|
159
|
+
(0, utils_1.debuglog)("Skipping updating subscription to closed node %s", subscriber.id);
|
|
173
160
|
}
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
161
|
+
}
|
|
162
|
+
pending.readyToAck = true;
|
|
163
|
+
this.maybeAckPendingContext(context);
|
|
177
164
|
}
|
|
178
165
|
}
|
|
179
166
|
exports.SourceMediaNode = SourceMediaNode;
|
|
@@ -283,94 +270,85 @@ class SinkMediaNode extends MediaNodeState {
|
|
|
283
270
|
}
|
|
284
271
|
this.sourceContextChange(done || (() => { }));
|
|
285
272
|
}
|
|
286
|
-
sourceContextChange(responseCallback) {
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
(
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
}));
|
|
314
|
-
});
|
|
315
|
-
}
|
|
273
|
+
async sourceContextChange(responseCallback) {
|
|
274
|
+
const stream = this.getGrpcStream();
|
|
275
|
+
if (stream.closed) {
|
|
276
|
+
// If the stream has been closed, not only don't try to send a new subscription, but signal that a response callback is not expected
|
|
277
|
+
// We really should remove the subscription to a closed node before it gets this far, but all the same definitely don't want to proceed
|
|
278
|
+
// here but instead might log an error.
|
|
279
|
+
return false;
|
|
280
|
+
}
|
|
281
|
+
const subscriberSources = [];
|
|
282
|
+
this.subscribedStreams = [];
|
|
283
|
+
this.currentSourcesActive = 0;
|
|
284
|
+
this.currentSources.forEach((selectors, source) => {
|
|
285
|
+
for (const selector of selectors) {
|
|
286
|
+
const pinSubscriptions = selector(source.outputStreams);
|
|
287
|
+
if (typescript_nullable_1.Nullable.isSome(pinSubscriptions)) {
|
|
288
|
+
this.currentSourcesActive += 1;
|
|
289
|
+
for (const pin in pinSubscriptions) {
|
|
290
|
+
pinSubscriptions[pin]?.forEach((key) => {
|
|
291
|
+
this.subscribedStreams.push(source.outputStreams.filter((streamMetadata) => streamMetadata.streamKey && (0, sdk_1.streamKeysAreEqual)(streamMetadata.streamKey, key))[0]);
|
|
292
|
+
subscriberSources.push((0, utils_1.provideFull)(media_pb_1.SubscribeSource, {
|
|
293
|
+
stream: (0, types_1.mkStreamKey)(key),
|
|
294
|
+
nodeId: (0, types_1.toMediaNodeId)(source.id),
|
|
295
|
+
input: pin == "auto"
|
|
296
|
+
? undefined
|
|
297
|
+
: (0, utils_1.provideFull)(media_pb_1.InputPin, { inputPin: pin }),
|
|
298
|
+
}));
|
|
299
|
+
});
|
|
316
300
|
}
|
|
317
301
|
}
|
|
318
|
-
}
|
|
319
|
-
const sources = Array.from(subscriberSources.values()).flat();
|
|
320
|
-
const id = (0, crypto_1.randomUUID)();
|
|
321
|
-
this.currentSubscription = (0, utils_1.provideFull)(media_pb_1.Subscription, { sources, id });
|
|
322
|
-
(0, utils_1.debuglog)("Node '%s' sending subscriptions %O", this.id, debugFormatSubscription(this.currentSubscription));
|
|
323
|
-
let subscribed = yield this.subscribeFn(this.currentSubscription);
|
|
324
|
-
if (subscribed)
|
|
325
|
-
this.subscriptionResponseCallbacks.set(id, responseCallback);
|
|
326
|
-
return subscribed;
|
|
302
|
+
}
|
|
327
303
|
});
|
|
304
|
+
const sources = Array.from(subscriberSources.values()).flat();
|
|
305
|
+
const id = (0, crypto_1.randomUUID)();
|
|
306
|
+
this.currentSubscription = (0, utils_1.provideFull)(media_pb_1.Subscription, { sources, id });
|
|
307
|
+
(0, utils_1.debuglog)("Node '%s' sending subscriptions %O", this.id, debugFormatSubscription(this.currentSubscription));
|
|
308
|
+
let subscribed = await this.subscribeFn(this.currentSubscription);
|
|
309
|
+
if (subscribed)
|
|
310
|
+
this.subscriptionResponseCallbacks.set(id, responseCallback);
|
|
311
|
+
return subscribed;
|
|
328
312
|
}
|
|
329
313
|
/** @internal */
|
|
330
|
-
subscriptionResponse(response) {
|
|
331
|
-
|
|
332
|
-
yield this.finaliseSubscription(response.id, response.error);
|
|
333
|
-
});
|
|
314
|
+
async subscriptionResponse(response) {
|
|
315
|
+
await this.finaliseSubscription(response.id, response.error);
|
|
334
316
|
}
|
|
335
317
|
/** @internal */
|
|
336
|
-
finaliseSubscription(id, err) {
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
if (
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
this.subscribedStreamsChangedFn(this.subscribedStreams);
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
|
-
else {
|
|
348
|
-
const error = (0, types_1.fromSubscriptionError)(err);
|
|
349
|
-
(0, utils_1.debuglog)("Node '%s' has a failed subscription response for '%s': %O", this.id, id, error);
|
|
350
|
-
callback(error);
|
|
351
|
-
if (this.subscribeErrorFn) {
|
|
352
|
-
this.subscribeErrorFn(error);
|
|
353
|
-
}
|
|
318
|
+
async finaliseSubscription(id, err) {
|
|
319
|
+
const callback = this.subscriptionResponseCallbacks.get(id);
|
|
320
|
+
this.subscriptionResponseCallbacks.delete(id);
|
|
321
|
+
if (callback) {
|
|
322
|
+
if (err === undefined) {
|
|
323
|
+
callback();
|
|
324
|
+
if (this.subscribedStreamsChangedFn) {
|
|
325
|
+
this.subscribedStreamsChangedFn(this.subscribedStreams);
|
|
354
326
|
}
|
|
355
327
|
}
|
|
356
328
|
else {
|
|
357
|
-
(0,
|
|
329
|
+
const error = (0, types_1.fromSubscriptionError)(err);
|
|
330
|
+
(0, utils_1.debuglog)("Node '%s' has a failed subscription response for '%s': %O", this.id, id, error);
|
|
331
|
+
callback(error);
|
|
332
|
+
if (this.subscribeErrorFn) {
|
|
333
|
+
this.subscribeErrorFn(error);
|
|
334
|
+
}
|
|
358
335
|
}
|
|
359
|
-
}
|
|
336
|
+
}
|
|
337
|
+
else {
|
|
338
|
+
(0, utils_1.debuglog)("Missing subscription response callback for '%s'", id);
|
|
339
|
+
}
|
|
360
340
|
}
|
|
361
341
|
/** @internal */
|
|
362
|
-
handleInboundContext(context) {
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
_ackContext(this.client, this.id, context);
|
|
373
|
-
});
|
|
342
|
+
async handleInboundContext(context) {
|
|
343
|
+
const validationResponse = this.subscriptionValidation((0, types_1.fromContext)(context));
|
|
344
|
+
const responseFn = util
|
|
345
|
+
.promisify(this.client.sendValidationResponse)
|
|
346
|
+
.bind(this.client);
|
|
347
|
+
await responseFn(new media_pb_1.ValidationResponse({
|
|
348
|
+
mediaNodeId: (0, types_1.toMediaNodeId)(this.id),
|
|
349
|
+
result: this.toValidationResponse(validationResponse),
|
|
350
|
+
}));
|
|
351
|
+
_ackContext(this.client, this.id, context);
|
|
374
352
|
}
|
|
375
353
|
/** @internal */
|
|
376
354
|
toValidationResponse(response) {
|
|
@@ -435,24 +413,21 @@ class AutoSinkMediaNode extends SinkMediaNode {
|
|
|
435
413
|
}
|
|
436
414
|
}
|
|
437
415
|
exports.AutoSinkMediaNode = AutoSinkMediaNode;
|
|
438
|
-
function _ackContext(client, id, context) {
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
}));
|
|
445
|
-
});
|
|
416
|
+
async function _ackContext(client, id, context) {
|
|
417
|
+
const fn = util.promisify(client.unblockCall).bind(client);
|
|
418
|
+
await fn((0, utils_1.provideFull)(media_pb_1.BlockingCallRef, {
|
|
419
|
+
mediaNodeId: (0, types_1.toMediaNodeId)(id),
|
|
420
|
+
blockingCallRef: context.blockingCallRef,
|
|
421
|
+
}));
|
|
446
422
|
}
|
|
447
423
|
/** @internal */
|
|
448
424
|
function registerStreamHandlers(grpcStream, unregisterNode, tag, reject, settings) {
|
|
449
425
|
const logError = (source, error) => {
|
|
450
|
-
var _a;
|
|
451
426
|
const err = error;
|
|
452
427
|
if (settings.onError) {
|
|
453
428
|
return;
|
|
454
429
|
}
|
|
455
|
-
console.log("Error:", source, err.code, constants_1.Status[err.code], err.details,
|
|
430
|
+
console.log("Error:", source, err.code, constants_1.Status[err.code], err.details, err.metadata?.getMap());
|
|
456
431
|
};
|
|
457
432
|
grpcStream.on("end", () => {
|
|
458
433
|
(0, utils_1.debuglog)(`End of ${tag} node`);
|
|
@@ -466,12 +441,12 @@ function registerStreamHandlers(grpcStream, unregisterNode, tag, reject, setting
|
|
|
466
441
|
logError(`${tag} node`, error);
|
|
467
442
|
settings.onError && settings.onError(error);
|
|
468
443
|
});
|
|
469
|
-
grpcStream.on("close", () =>
|
|
444
|
+
grpcStream.on("close", async () => {
|
|
470
445
|
(0, utils_1.debuglog)(`${tag} node close`);
|
|
471
|
-
settings.onClose &&
|
|
446
|
+
settings.onClose && await settings.onClose();
|
|
472
447
|
unregisterNode();
|
|
473
448
|
reject();
|
|
474
|
-
})
|
|
449
|
+
});
|
|
475
450
|
}
|
|
476
451
|
exports.registerStreamHandlers = registerStreamHandlers;
|
|
477
452
|
////////////////////////////////////////////////////////////////////////////////
|
|
@@ -550,22 +525,20 @@ function debugFormatSubscription(subscription) {
|
|
|
550
525
|
};
|
|
551
526
|
}
|
|
552
527
|
function debugFormatSubscriptionSource(subscriptionSource) {
|
|
553
|
-
var _a, _b;
|
|
554
528
|
return {
|
|
555
|
-
destNodeId:
|
|
556
|
-
destPin:
|
|
529
|
+
destNodeId: subscriptionSource.nodeId?.id,
|
|
530
|
+
destPin: subscriptionSource.input?.inputPin,
|
|
557
531
|
sourceStreamKey: debugFormatStreamKey(subscriptionSource.stream),
|
|
558
532
|
};
|
|
559
533
|
}
|
|
560
534
|
function debugFormatStreamKey(streamKey) {
|
|
561
|
-
var _a, _b, _c, _d;
|
|
562
535
|
if (streamKey === undefined)
|
|
563
536
|
return streamKey;
|
|
564
537
|
return {
|
|
565
|
-
sourceName:
|
|
566
|
-
programNumber:
|
|
567
|
-
streamId:
|
|
568
|
-
renditionName:
|
|
538
|
+
sourceName: streamKey.sourceName?.sourceName,
|
|
539
|
+
programNumber: streamKey.programNumber?.programNumber,
|
|
540
|
+
streamId: streamKey.streamId?.streamId,
|
|
541
|
+
renditionName: streamKey.renditionName?.renditionName,
|
|
569
542
|
};
|
|
570
543
|
}
|
|
571
544
|
function debugFormatStruct(details) {
|
|
@@ -1,13 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
3
|
exports.StreamTimestampReportNode = void 0;
|
|
13
4
|
const media_pb_1 = require("@norskvideo/norsk-api/lib/media_pb");
|
|
@@ -21,9 +12,7 @@ const types_1 = require("./types");
|
|
|
21
12
|
class StreamTimestampReportNode extends common_1.AutoSinkMediaNode {
|
|
22
13
|
/** @internal */
|
|
23
14
|
constructor(settings, client, unregisterNode) {
|
|
24
|
-
super(client, () => this.grpcStream, (subscription) =>
|
|
25
|
-
return this.grpcStream.write((0, common_1.provideFull)(media_pb_1.StreamTimestampReportMessage, (0, common_1.mkMessageCase)({ subscription })));
|
|
26
|
-
}), settings.onSubscriptionError);
|
|
15
|
+
super(client, () => this.grpcStream, async (subscription) => this.grpcStream.write((0, common_1.provideFull)(media_pb_1.StreamTimestampReportMessage, (0, common_1.mkMessageCase)({ subscription }))), settings.onSubscriptionError);
|
|
27
16
|
const config = (0, common_1.provideFull)(media_pb_1.StreamTimestampReportConfiguration, {
|
|
28
17
|
id: settings.id ? (0, common_1.provideFull)(media_pb_2.MediaNodeId, {
|
|
29
18
|
id: settings.id
|
|
@@ -66,12 +55,10 @@ class StreamTimestampReportNode extends common_1.AutoSinkMediaNode {
|
|
|
66
55
|
});
|
|
67
56
|
}
|
|
68
57
|
/** @internal */
|
|
69
|
-
static create(settings, client, unregisterNode) {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
return node;
|
|
74
|
-
});
|
|
58
|
+
static async create(settings, client, unregisterNode) {
|
|
59
|
+
const node = new StreamTimestampReportNode(settings, client, unregisterNode);
|
|
60
|
+
await node.initialised;
|
|
61
|
+
return node;
|
|
75
62
|
}
|
|
76
63
|
}
|
|
77
64
|
exports.StreamTimestampReportNode = StreamTimestampReportNode;
|