@eluvio/elv-client-js 4.0.76 → 4.0.78

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 (37) hide show
  1. package/dist/ElvClient-min.js +18 -10
  2. package/dist/ElvClient-node-min.js +18 -10
  3. package/dist/ElvFrameClient-min.js +9 -9
  4. package/dist/ElvPermissionsClient-min.js +10 -10
  5. package/dist/ElvWalletClient-min.js +18 -10
  6. package/dist/ElvWalletClient-node-min.js +18 -10
  7. package/dist/src/AuthorizationClient.js +18 -12
  8. package/dist/src/Crypto.js +2 -2
  9. package/dist/src/ElvClient.js +111 -76
  10. package/dist/src/EthClient.js +2 -2
  11. package/dist/src/FrameClient.js +4 -4
  12. package/dist/src/PermissionsClient.js +2 -2
  13. package/dist/src/Utils.js +6 -5
  14. package/dist/src/abr_profiles/abr_profile_live_drm.js +1621 -0
  15. package/dist/src/abr_profiles/abr_profile_live_to_vod.js +1599 -0
  16. package/dist/src/client/ABRPublishing.js +2 -2
  17. package/dist/src/client/AccessGroups.js +19 -20
  18. package/dist/src/client/ContentAccess.js +48 -28
  19. package/dist/src/client/ContentManagement.js +3 -3
  20. package/dist/src/client/Contracts.js +235 -203
  21. package/dist/src/client/Files.js +2 -2
  22. package/dist/src/client/LiveConf.js +152 -21
  23. package/dist/src/client/LiveStream.js +1376 -1248
  24. package/dist/src/client/NFT.js +2 -2
  25. package/dist/src/contracts/v3b/BaseAccessControlGroup.js +1704 -0
  26. package/dist/src/walletClient/ClientMethods.js +423 -280
  27. package/dist/src/walletClient/Profile.js +2 -2
  28. package/dist/src/walletClient/Utils.js +7 -3
  29. package/dist/src/walletClient/index.js +124 -44
  30. package/package.json +2 -1
  31. package/src/FrameClient.js +4 -0
  32. package/src/abr_profiles/abr_profile_live_drm.js +1907 -0
  33. package/src/abr_profiles/abr_profile_live_to_vod.js +1885 -0
  34. package/src/client/ContentAccess.js +21 -0
  35. package/src/client/LiveConf.js +133 -17
  36. package/src/client/LiveStream.js +907 -947
  37. package/testScripts/Test.js +7 -0
@@ -1,3 +1,5 @@
1
+ var _toConsumableArray = require("@babel/runtime/helpers/toConsumableArray");
2
+ var _defineProperty = require("@babel/runtime/helpers/defineProperty");
1
3
  var _regeneratorRuntime = require("@babel/runtime/regenerator");
2
4
  var _asyncToGenerator = require("@babel/runtime/helpers/asyncToGenerator");
3
5
  /**
@@ -11,13 +13,7 @@ var _require = require("./LiveConf"),
11
13
  var path = require("path");
12
14
  var fs = require("fs");
13
15
  var HttpClient = require("../HttpClient");
14
- //
15
- // const {
16
- // ValidateLibrary,
17
- // ValidateVersion,
18
- // ValidateParameters
19
- // } = require("../Validation");
20
-
16
+ var Fraction = require("fraction.js");
21
17
  var MakeTxLessToken = /*#__PURE__*/function () {
22
18
  var _ref2 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(_ref) {
23
19
  var client, libraryId, objectId, versionHash, tok;
@@ -47,20 +43,291 @@ var MakeTxLessToken = /*#__PURE__*/function () {
47
43
  return _ref2.apply(this, arguments);
48
44
  };
49
45
  }();
50
- function sleep(ms) {
46
+ var Sleep = function Sleep(ms) {
51
47
  return new Promise(function (resolve) {
52
48
  return setTimeout(resolve, ms);
53
49
  });
54
- }
50
+ };
51
+
52
+ /**
53
+ * Set the offering for the live stream
54
+ *
55
+ * @methodGroup Live Stream
56
+ * @namedParams
57
+ * @param {Object} client - The client object
58
+ * @param {string} libraryId - ID of the library for the new live stream object
59
+ * @param {string} objectId - ID of the new live stream object
60
+ * @param {string=} typeAbrMaster - Content type hash
61
+ * @param {string=} typeLiveStream - Content type hash
62
+ * @param {string} streamUrl - Live source URL
63
+ * @param {object} abrProfile - ABR Profile for the offering
64
+ * @param {number} aBitRate - Audio bitrate
65
+ * @param {number} aChannels - Audio channels
66
+ * @param {number} aSampleRate - Audio sample rate
67
+ * @param {number} aStreamIndex - Audio stream index
68
+ * @param {string} aTimeBase - Audio time base as a fraction, e.g. "1/48000" (usually equal to 1/aSampleRate)
69
+ * @param {string} aChannelLayout - Channel layout, e.g. "stereo"
70
+ * @param {number} vBitRate - Video bitrate
71
+ * @param {number} vHeight - Video height
72
+ * @param {number} vStreamIndex - Video stream index
73
+ * @param {number} vWidth - Video width
74
+ * @param {string} vDisplayAspectRatio - Display aspect ratio as a fraction, e.g. "16/9"
75
+ * @param {string} vFrameRate - Frame rate as an integer, e.g. "30"
76
+ * @param {string} vTimeBase - Time base as a fraction, e.g. "1/30000"
77
+ *
78
+ * @return {Promise<string>} - Final hash of the live stream object
79
+ */
80
+ var StreamGenerateOffering = /*#__PURE__*/function () {
81
+ var _ref4 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee2(_ref3) {
82
+ var client, libraryId, objectId, typeAbrMaster, typeLiveStream, streamUrl, abrProfile, aBitRate, aChannels, aSampleRate, aStreamIndex, aTimeBase, aChannelLayout, vBitRate, vHeight, vStreamIndex, vWidth, vDisplayAspectRatio, vFrameRate, vTimeBase, DUMMY_DURATION, aDurationTs, vDurationTs, sourceAudioStream, sourceVideoStream, DUMMY_STREAM, sourceStreams, maxStreamIndex, i, sources, variants, production_master, metadata, editResponse, writeToken, finalizeResponse, masterVersionHash, createResponse, versionHash, finalHash;
83
+ return _regeneratorRuntime.wrap(function _callee2$(_context2) {
84
+ while (1) switch (_context2.prev = _context2.next) {
85
+ case 0:
86
+ client = _ref3.client, libraryId = _ref3.libraryId, objectId = _ref3.objectId, typeAbrMaster = _ref3.typeAbrMaster, typeLiveStream = _ref3.typeLiveStream, streamUrl = _ref3.streamUrl, abrProfile = _ref3.abrProfile, aBitRate = _ref3.aBitRate, aChannels = _ref3.aChannels, aSampleRate = _ref3.aSampleRate, aStreamIndex = _ref3.aStreamIndex, aTimeBase = _ref3.aTimeBase, aChannelLayout = _ref3.aChannelLayout, vBitRate = _ref3.vBitRate, vHeight = _ref3.vHeight, vStreamIndex = _ref3.vStreamIndex, vWidth = _ref3.vWidth, vDisplayAspectRatio = _ref3.vDisplayAspectRatio, vFrameRate = _ref3.vFrameRate, vTimeBase = _ref3.vTimeBase;
87
+ // compute duration_ts
88
+ DUMMY_DURATION = 1001; // should result in integer duration_ts values for both audio and video
89
+ aDurationTs = Fraction(aTimeBase).inverse().mul(DUMMY_DURATION).valueOf();
90
+ vDurationTs = Fraction(vTimeBase).inverse().mul(DUMMY_DURATION).valueOf(); // construct /production_master/sources/STREAM_URL/streams
91
+ sourceAudioStream = {
92
+ "bit_rate": aBitRate,
93
+ "channel_layout": aChannelLayout,
94
+ "channels": aChannels,
95
+ "codec_name": "aac",
96
+ "duration": DUMMY_DURATION,
97
+ "duration_ts": aDurationTs,
98
+ "frame_count": 0,
99
+ "language": "",
100
+ "max_bit_rate": aBitRate,
101
+ "sample_rate": aSampleRate,
102
+ "start_pts": 0,
103
+ "start_time": 0,
104
+ "time_base": aTimeBase,
105
+ "type": "StreamAudio"
106
+ };
107
+ sourceVideoStream = {
108
+ "bit_rate": vBitRate,
109
+ "codec_name": "h264",
110
+ "display_aspect_ratio": vDisplayAspectRatio,
111
+ "duration": DUMMY_DURATION,
112
+ "duration_ts": vDurationTs,
113
+ "field_order": "progressive",
114
+ "frame_count": 0,
115
+ "frame_rate": vFrameRate,
116
+ "hdr": null,
117
+ "height": vHeight,
118
+ "language": "",
119
+ "max_bit_rate": vBitRate,
120
+ "sample_aspect_ratio": "1",
121
+ "start_pts": 0,
122
+ "start_time": 0,
123
+ "time_base": vTimeBase,
124
+ "type": "StreamVideo",
125
+ "width": vWidth
126
+ }; // placeholder stream to use if [aStreamIndex, vStreamIndex].sort() is not [0,1]
127
+ DUMMY_STREAM = {
128
+ "bit_rate": 0,
129
+ "codec_name": "",
130
+ "duration": DUMMY_DURATION,
131
+ "duration_ts": 2500 * DUMMY_DURATION,
132
+ "frame_count": 1,
133
+ "language": "",
134
+ "max_bit_rate": 0,
135
+ "start_pts": 0,
136
+ "start_time": 0,
137
+ "time_base": "1/2500",
138
+ "type": "StreamData"
139
+ };
140
+ sourceStreams = [];
141
+ maxStreamIndex = Math.max(aStreamIndex, vStreamIndex);
142
+ for (i = 0; i <= maxStreamIndex; i++) {
143
+ if (i === aStreamIndex) {
144
+ sourceStreams.push(sourceAudioStream);
145
+ } else if (i === vStreamIndex) {
146
+ sourceStreams.push(sourceVideoStream);
147
+ } else {
148
+ sourceStreams.push(DUMMY_STREAM);
149
+ }
150
+ }
151
+
152
+ // construct /production_master/sources
153
+ sources = _defineProperty({}, streamUrl, {
154
+ "container_format": {
155
+ "duration": DUMMY_DURATION,
156
+ "filename": streamUrl,
157
+ "format_name": "mov,mp4,m4a,3gp,3g2,mj2",
158
+ "start_time": 0
159
+ },
160
+ "streams": sourceStreams
161
+ }); // construct /production_master/variants
162
+ variants = {
163
+ "default": {
164
+ "streams": {
165
+ "audio": {
166
+ "default_for_media_type": false,
167
+ "label": "",
168
+ "language": "",
169
+ "mapping_info": "",
170
+ "sources": [{
171
+ "files_api_path": streamUrl,
172
+ "stream_index": aStreamIndex
173
+ }]
174
+ },
175
+ "video": {
176
+ "default_for_media_type": false,
177
+ "label": "",
178
+ "language": "",
179
+ "mapping_info": "",
180
+ "sources": [{
181
+ "files_api_path": streamUrl,
182
+ "stream_index": vStreamIndex
183
+ }]
184
+ }
185
+ }
186
+ }
187
+ }; // construct /production_master
188
+ production_master = {
189
+ sources: sources,
190
+ variants: variants
191
+ }; // get existing metadata
192
+ console.log("Retrieving current metadata...");
193
+ _context2.next = 16;
194
+ return client.ContentObjectMetadata({
195
+ libraryId: libraryId,
196
+ objectId: objectId
197
+ });
198
+ case 16:
199
+ metadata = _context2.sent;
200
+ // add /production_master to metadata
201
+ metadata.production_master = production_master;
202
+
203
+ // write back to object
204
+ console.log("Getting write token...");
205
+ _context2.next = 21;
206
+ return client.EditContentObject({
207
+ libraryId: libraryId,
208
+ objectId: objectId,
209
+ options: {
210
+ type: typeAbrMaster
211
+ }
212
+ });
213
+ case 21:
214
+ editResponse = _context2.sent;
215
+ writeToken = editResponse.write_token;
216
+ console.log("New write token: ".concat(writeToken));
217
+ console.log("Writing back metadata with /production_master added...");
218
+ _context2.next = 27;
219
+ return client.ReplaceMetadata({
220
+ libraryId: libraryId,
221
+ metadata: metadata,
222
+ objectId: objectId,
223
+ writeToken: writeToken
224
+ });
225
+ case 27:
226
+ console.log("Finalizing...");
227
+ _context2.next = 30;
228
+ return client.FinalizeContentObject({
229
+ libraryId: libraryId,
230
+ objectId: objectId,
231
+ writeToken: writeToken
232
+ });
233
+ case 30:
234
+ finalizeResponse = _context2.sent;
235
+ masterVersionHash = finalizeResponse.hash;
236
+ console.log("Finalized, new version hash: ".concat(masterVersionHash));
237
+
238
+ // Generate offering
239
+ _context2.next = 35;
240
+ return client.CreateABRMezzanine({
241
+ libraryId: libraryId,
242
+ objectId: objectId,
243
+ masterVersionHash: masterVersionHash,
244
+ variant: "default",
245
+ offeringKey: "default",
246
+ abrProfile: abrProfile
247
+ });
248
+ case 35:
249
+ createResponse = _context2.sent;
250
+ if (createResponse.warnings.length > 0) {
251
+ console.log("WARNINGS:");
252
+ console.log(JSON.stringify(createResponse.warnings, null, 2));
253
+ }
254
+ if (createResponse.errors.length > 0) {
255
+ console.log("ERRORS:");
256
+ console.log(JSON.stringify(createResponse.errors, null, 2));
257
+ }
258
+ versionHash = createResponse.hash;
259
+ console.log("New version hash: ".concat(versionHash));
260
+
261
+ // get new metadata
262
+ console.log("Retrieving revised metadata with offering...");
263
+ _context2.next = 43;
264
+ return client.ContentObjectMetadata({
265
+ libraryId: libraryId,
266
+ versionHash: versionHash
267
+ });
268
+ case 43:
269
+ metadata = _context2.sent;
270
+ console.log("Moving /abr_mezzanine/offerings to /offerings and removing /abr_mezzanine...");
271
+ metadata.offerings = metadata.abr_mezzanine.offerings;
272
+ delete metadata.abr_mezzanine;
273
+
274
+ // add items to media_struct needed to use options.json handler
275
+ metadata.offerings["default"].media_struct.duration_rat = "".concat(DUMMY_DURATION);
276
+
277
+ // write back to object
278
+ console.log("Getting write token...");
279
+ _context2.next = 51;
280
+ return client.EditContentObject({
281
+ libraryId: libraryId,
282
+ objectId: objectId,
283
+ options: {
284
+ type: typeLiveStream
285
+ }
286
+ });
287
+ case 51:
288
+ editResponse = _context2.sent;
289
+ writeToken = editResponse.write_token;
290
+ console.log("New write token: ".concat(writeToken));
291
+ console.log("Writing back metadata with /offerings...");
292
+ _context2.next = 57;
293
+ return client.ReplaceMetadata({
294
+ libraryId: libraryId,
295
+ metadata: metadata,
296
+ objectId: objectId,
297
+ writeToken: writeToken
298
+ });
299
+ case 57:
300
+ console.log("Finalizing...");
301
+ _context2.next = 60;
302
+ return client.FinalizeContentObject({
303
+ libraryId: libraryId,
304
+ objectId: objectId,
305
+ writeToken: writeToken
306
+ });
307
+ case 60:
308
+ finalizeResponse = _context2.sent;
309
+ finalHash = finalizeResponse.hash;
310
+ console.log("Finalized, new version hash: ".concat(finalHash));
311
+ return _context2.abrupt("return", finalHash);
312
+ case 64:
313
+ case "end":
314
+ return _context2.stop();
315
+ }
316
+ }, _callee2);
317
+ }));
318
+ return function StreamGenerateOffering(_x2) {
319
+ return _ref4.apply(this, arguments);
320
+ };
321
+ }();
55
322
 
56
323
  /**
57
324
  * Retrieve the status of the current live stream session
58
325
  *
59
326
  * @methodGroup Live Stream
60
327
  * @namedParams
61
- * @param {string} name -
62
- * @param {boolean} stopLro -
63
- * @param {boolean} showParams -
328
+ * @param {string} name - Object ID or name of the live stream object
329
+ * @param {boolean=} stopLro - If specified, will stop LRO
330
+ * @param {boolean=} showParams - If specified, will return recording_params with status
64
331
  * States:
65
332
  * unconfigured - no live_recording_config
66
333
  * uninitialized - no live_recording config generated
@@ -70,64 +337,65 @@ function sleep(ms) {
70
337
  * running - stream is running and producing output
71
338
  * stalled - LRO running but no source data (so not producing output)
72
339
  *
73
- * @return {Object} - The status response for the object, as well as logs, warnings and errors from the master initialization
340
+ * @return {Promise<Object>} - The status response for the object, as well as logs, warnings and errors from the master initialization
74
341
  */
75
342
  exports.StreamStatus = /*#__PURE__*/function () {
76
- var _ref4 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee2(_ref3) {
77
- var name, _ref3$stopLro, stopLro, _ref3$showParams, showParams, conf, status, libraryId, mainMeta, fabURI, edgeWriteToken, edgeMeta, recordings, sequence, period, tlro, sinceLastFinalize, recording_period, insertions, i, insertionTimeSinceEpoch, state, lroStatus, playout_urls, objectId, playout_options, hls_clear_enabled, hls_aes128_enabled, hls_sample_aes_enabled, networkInfo, token, embed_net, embed_url;
78
- return _regeneratorRuntime.wrap(function _callee2$(_context2) {
79
- while (1) switch (_context2.prev = _context2.next) {
343
+ var _ref6 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee3(_ref5) {
344
+ var name, _ref5$stopLro, stopLro, _ref5$showParams, showParams, conf, status, libraryId, mainMeta, fabURI, edgeWriteToken, edgeMeta, recordings, sequence, period, tlro, sinceLastFinalize, recording_period, insertions, i, insertionTimeSinceEpoch, state, lroStatus, playout_urls, objectId, playout_options, hls_clear_enabled, hls_aes128_enabled, hls_sample_aes_enabled, networkInfo, token, embed_net, embed_url;
345
+ return _regeneratorRuntime.wrap(function _callee3$(_context3) {
346
+ while (1) switch (_context3.prev = _context3.next) {
80
347
  case 0:
81
- name = _ref3.name, _ref3$stopLro = _ref3.stopLro, stopLro = _ref3$stopLro === void 0 ? false : _ref3$stopLro, _ref3$showParams = _ref3.showParams, showParams = _ref3$showParams === void 0 ? false : _ref3$showParams;
82
- _context2.next = 3;
348
+ name = _ref5.name, _ref5$stopLro = _ref5.stopLro, stopLro = _ref5$stopLro === void 0 ? false : _ref5$stopLro, _ref5$showParams = _ref5.showParams, showParams = _ref5$showParams === void 0 ? false : _ref5$showParams;
349
+ _context3.next = 3;
83
350
  return this.LoadConf({
84
351
  name: name
85
352
  });
86
353
  case 3:
87
- conf = _context2.sent;
354
+ conf = _context3.sent;
88
355
  status = {
89
356
  name: name
90
357
  };
91
- _context2.prev = 5;
92
- _context2.next = 8;
358
+ _context3.prev = 5;
359
+ _context3.next = 8;
93
360
  return this.ContentObjectLibraryId({
94
361
  objectId: conf.objectId
95
362
  });
96
363
  case 8:
97
- libraryId = _context2.sent;
364
+ libraryId = _context3.sent;
98
365
  status.library_id = libraryId;
99
366
  status.object_id = conf.objectId;
100
- _context2.next = 13;
367
+ _context3.next = 13;
101
368
  return this.ContentObjectMetadata({
102
369
  libraryId: libraryId,
103
370
  objectId: conf.objectId,
104
371
  select: ["live_recording_config", "live_recording"]
105
372
  });
106
373
  case 13:
107
- mainMeta = _context2.sent;
374
+ mainMeta = _context3.sent;
375
+ status.reference_url = mainMeta.live_recording_config.reference_url;
108
376
  if (!(mainMeta.live_recording_config == undefined || mainMeta.live_recording_config.url == undefined)) {
109
- _context2.next = 17;
377
+ _context3.next = 18;
110
378
  break;
111
379
  }
112
380
  status.state = "unconfigured";
113
- return _context2.abrupt("return", status);
114
- case 17:
381
+ return _context3.abrupt("return", status);
382
+ case 18:
115
383
  if (!(mainMeta.live_recording == undefined || mainMeta.live_recording.fabric_config == undefined || mainMeta.live_recording.playout_config == undefined || mainMeta.live_recording.recording_config == undefined)) {
116
- _context2.next = 20;
384
+ _context3.next = 21;
117
385
  break;
118
386
  }
119
387
  status.state = "uninitialized";
120
- return _context2.abrupt("return", status);
121
- case 20:
388
+ return _context3.abrupt("return", status);
389
+ case 21:
122
390
  fabURI = mainMeta.live_recording.fabric_config.ingress_node_api;
123
391
  if (!(fabURI === undefined)) {
124
- _context2.next = 25;
392
+ _context3.next = 26;
125
393
  break;
126
394
  }
127
395
  console.log("bad fabric config - missing ingress node API");
128
396
  status.state = "uninitialized";
129
- return _context2.abrupt("return", status);
130
- case 25:
397
+ return _context3.abrupt("return", status);
398
+ case 26:
131
399
  // Support both hostname and URL ingress_node_api
132
400
  if (!fabURI.startsWith("http")) {
133
401
  // Assume https
@@ -136,35 +404,38 @@ exports.StreamStatus = /*#__PURE__*/function () {
136
404
  status.fabric_api = fabURI;
137
405
  status.url = mainMeta.live_recording.recording_config.recording_params.origin_url;
138
406
  edgeWriteToken = mainMeta.live_recording.fabric_config.edge_write_token;
139
- if (!(edgeWriteToken == undefined)) {
140
- _context2.next = 32;
407
+ if (edgeWriteToken) {
408
+ _context3.next = 33;
141
409
  break;
142
410
  }
143
411
  status.state = "inactive";
144
- return _context2.abrupt("return", status);
145
- case 32:
412
+ return _context3.abrupt("return", status);
413
+ case 33:
146
414
  this.RecordWriteToken({
147
415
  writeToken: edgeWriteToken,
148
416
  fabricNodeUrl: fabURI
149
417
  });
150
418
  status.edge_write_token = edgeWriteToken;
151
419
  status.stream_id = edgeWriteToken; // By convention the stream ID is its write token
152
- _context2.next = 37;
420
+ _context3.next = 38;
153
421
  return this.ContentObjectMetadata({
154
422
  libraryId: libraryId,
155
423
  objectId: conf.objectId,
156
424
  writeToken: edgeWriteToken,
157
425
  select: ["live_recording"]
158
426
  });
159
- case 37:
160
- edgeMeta = _context2.sent;
427
+ case 38:
428
+ edgeMeta = _context3.sent;
429
+ status.edge_meta_size = JSON.stringify(edgeMeta).length;
430
+
431
+ // If a stream has never been started return state 'inactive'
161
432
  if (!(edgeMeta.live_recording === undefined || edgeMeta.live_recording.recordings === undefined || edgeMeta.live_recording.recordings.recording_sequence === undefined)) {
162
- _context2.next = 41;
433
+ _context3.next = 43;
163
434
  break;
164
435
  }
165
436
  status.state = "stopped";
166
- return _context2.abrupt("return", status);
167
- case 41:
437
+ return _context3.abrupt("return", status);
438
+ case 43:
168
439
  recordings = edgeMeta.live_recording.recordings;
169
440
  status.recording_period_sequence = recordings.recording_sequence;
170
441
  sequence = recordings.recording_sequence;
@@ -183,15 +454,15 @@ exports.StreamStatus = /*#__PURE__*/function () {
183
454
  video_since_last_finalize_sec: sinceLastFinalize
184
455
  };
185
456
  status.recording_period = recording_period;
186
- _context2.next = 52;
457
+ _context3.next = 54;
187
458
  return this.FabricUrl({
188
459
  libraryId: libraryId,
189
460
  objectId: conf.objectId,
190
461
  writeToken: edgeWriteToken,
191
462
  call: "live/status/" + tlro
192
463
  });
193
- case 52:
194
- status.lro_status_url = _context2.sent;
464
+ case 54:
465
+ status.lro_status_url = _context3.sent;
195
466
  status.insertions = [];
196
467
  if (edgeMeta.live_recording.playout_config.interleaves != undefined && edgeMeta.live_recording.playout_config.interleaves[sequence] != undefined) {
197
468
  insertions = edgeMeta.live_recording.playout_config.interleaves[sequence];
@@ -206,31 +477,31 @@ exports.StreamStatus = /*#__PURE__*/function () {
206
477
  }
207
478
  }
208
479
  if (showParams) {
209
- status.recording_paramse = edgeMeta.live_recording.recording_config.recording_params;
480
+ status.recording_params = edgeMeta.live_recording.recording_config.recording_params;
210
481
  }
211
482
  state = "stopped";
212
483
  lroStatus = "";
213
- _context2.prev = 58;
214
- _context2.t0 = this.utils;
215
- _context2.next = 62;
484
+ _context3.prev = 60;
485
+ _context3.t0 = this.utils;
486
+ _context3.next = 64;
216
487
  return HttpClient.Fetch(status.lro_status_url);
217
- case 62:
218
- _context2.t1 = _context2.sent;
219
- _context2.next = 65;
220
- return _context2.t0.ResponseToJson.call(_context2.t0, _context2.t1);
221
- case 65:
222
- lroStatus = _context2.sent;
488
+ case 64:
489
+ _context3.t1 = _context3.sent;
490
+ _context3.next = 67;
491
+ return _context3.t0.ResponseToJson.call(_context3.t0, _context3.t1);
492
+ case 67:
493
+ lroStatus = _context3.sent;
223
494
  state = lroStatus.state;
224
- _context2.next = 75;
495
+ _context3.next = 77;
225
496
  break;
226
- case 69:
227
- _context2.prev = 69;
228
- _context2.t2 = _context2["catch"](58);
229
- console.log("LRO Status (failed): ", _context2.t2.response.statusCode);
497
+ case 71:
498
+ _context3.prev = 71;
499
+ _context3.t2 = _context3["catch"](60);
500
+ console.log("LRO Status (failed): ", _context3.t2.response.statusCode);
230
501
  status.state = "stopped";
231
- status.error = _context2.t2.response;
232
- return _context2.abrupt("return", status);
233
- case 75:
502
+ status.error = _context3.t2.response;
503
+ return _context3.abrupt("return", status);
504
+ case 77:
234
505
  // Convert LRO 'state' to desired 'state'
235
506
  if (state === "running" && period.video_finalized_parts_info.last_finalization_time === 0) {
236
507
  state = "starting";
@@ -241,98 +512,98 @@ exports.StreamStatus = /*#__PURE__*/function () {
241
512
  }
242
513
  status.state = state;
243
514
  if (!((state === "running" || state === "stalled" || state === "starting") && stopLro)) {
244
- _context2.next = 96;
515
+ _context3.next = 98;
245
516
  break;
246
517
  }
247
- _context2.next = 80;
518
+ _context3.next = 82;
248
519
  return this.FabricUrl({
249
520
  libraryId: libraryId,
250
521
  objectId: conf.objectId,
251
522
  writeToken: edgeWriteToken,
252
523
  call: "live/stop/" + tlro
253
524
  });
254
- case 80:
255
- lroStopUrl = _context2.sent;
256
- _context2.prev = 81;
257
- _context2.t3 = this.utils;
258
- _context2.next = 85;
525
+ case 82:
526
+ lroStopUrl = _context3.sent;
527
+ _context3.prev = 83;
528
+ _context3.t3 = this.utils;
529
+ _context3.next = 87;
259
530
  return HttpClient.Fetch(lroStopUrl);
260
- case 85:
261
- _context2.t4 = _context2.sent;
262
- _context2.next = 88;
263
- return _context2.t3.ResponseToJson.call(_context2.t3, _context2.t4);
264
- case 88:
531
+ case 87:
532
+ _context3.t4 = _context3.sent;
533
+ _context3.next = 90;
534
+ return _context3.t3.ResponseToJson.call(_context3.t3, _context3.t4);
535
+ case 90:
265
536
  console.log("LRO Stop: ", lroStatus.body);
266
- _context2.next = 94;
537
+ _context3.next = 96;
267
538
  break;
268
- case 91:
269
- _context2.prev = 91;
270
- _context2.t5 = _context2["catch"](81);
271
- console.log("LRO Stop (failed): ", _context2.t5.response.statusCode);
272
- case 94:
539
+ case 93:
540
+ _context3.prev = 93;
541
+ _context3.t5 = _context3["catch"](83);
542
+ console.log("LRO Stop (failed): ", _context3.t5.response.statusCode);
543
+ case 96:
273
544
  state = "stopped";
274
545
  status.state = state;
275
- case 96:
546
+ case 98:
276
547
  if (!(state === "running")) {
277
- _context2.next = 128;
548
+ _context3.next = 130;
278
549
  break;
279
550
  }
280
551
  playout_urls = {};
281
552
  objectId = conf.objectId;
282
- _context2.next = 101;
553
+ _context3.next = 103;
283
554
  return this.PlayoutOptions({
284
555
  objectId: objectId,
285
556
  linkPath: "public/asset_metadata/sources/default"
286
557
  });
287
- case 101:
288
- playout_options = _context2.sent;
558
+ case 103:
559
+ playout_options = _context3.sent;
289
560
  hls_clear_enabled = playout_options && playout_options.hls && playout_options.hls.playoutMethods && playout_options.hls.playoutMethods.clear !== undefined;
290
561
  if (!hls_clear_enabled) {
291
- _context2.next = 107;
562
+ _context3.next = 109;
292
563
  break;
293
564
  }
294
- _context2.next = 106;
565
+ _context3.next = 108;
295
566
  return this.FabricUrl({
296
567
  libraryId: libraryId,
297
568
  objectId: objectId,
298
569
  rep: "playout/default/hls-clear/playlist.m3u8"
299
570
  });
300
- case 106:
301
- playout_urls.hls_clear = _context2.sent;
302
- case 107:
571
+ case 108:
572
+ playout_urls.hls_clear = _context3.sent;
573
+ case 109:
303
574
  hls_aes128_enabled = playout_options && playout_options.hls && playout_options.hls.playoutMethods && playout_options.hls.playoutMethods["aes-128"] !== undefined;
304
575
  if (!hls_aes128_enabled) {
305
- _context2.next = 112;
576
+ _context3.next = 114;
306
577
  break;
307
578
  }
308
- _context2.next = 111;
579
+ _context3.next = 113;
309
580
  return this.FabricUrl({
310
581
  libraryId: libraryId,
311
582
  objectId: objectId,
312
583
  rep: "playout/default/hls-aes128/playlist.m3u8"
313
584
  });
314
- case 111:
315
- playout_urls.hls_aes128 = _context2.sent;
316
- case 112:
585
+ case 113:
586
+ playout_urls.hls_aes128 = _context3.sent;
587
+ case 114:
317
588
  hls_sample_aes_enabled = playout_options && playout_options.hls && playout_options.hls.playoutMethods && playout_options.hls.playoutMethods["sample-aes"] !== undefined;
318
589
  if (!hls_sample_aes_enabled) {
319
- _context2.next = 117;
590
+ _context3.next = 119;
320
591
  break;
321
592
  }
322
- _context2.next = 116;
593
+ _context3.next = 118;
323
594
  return this.FabricUrl({
324
595
  libraryId: libraryId,
325
596
  objectId: objectId,
326
597
  rep: "playout/default/hls-sample-aes/playlist.m3u8"
327
598
  });
328
- case 116:
329
- playout_urls.hls_sample_aes = _context2.sent;
330
- case 117:
331
- _context2.next = 119;
332
- return this.NetworkInfo();
599
+ case 118:
600
+ playout_urls.hls_sample_aes = _context3.sent;
333
601
  case 119:
334
- networkInfo = _context2.sent;
335
- _context2.next = 122;
602
+ _context3.next = 121;
603
+ return this.NetworkInfo();
604
+ case 121:
605
+ networkInfo = _context3.sent;
606
+ _context3.next = 124;
336
607
  return this.authClient.AuthorizationToken({
337
608
  libraryId: libraryId,
338
609
  objectId: objectId,
@@ -340,8 +611,8 @@ exports.StreamStatus = /*#__PURE__*/function () {
340
611
  noCache: true,
341
612
  noAuth: true
342
613
  });
343
- case 122:
344
- token = _context2.sent;
614
+ case 124:
615
+ token = _context3.sent;
345
616
  embed_net = "main";
346
617
  if (networkInfo.name.includes("demo")) {
347
618
  embed_net = "demo";
@@ -349,92 +620,75 @@ exports.StreamStatus = /*#__PURE__*/function () {
349
620
  embed_url = "https://embed.v3.contentfabric.io/?net=".concat(embed_net, "&p&ct=h&oid=").concat(conf.objectId, "&mt=lv&ath=").concat(token);
350
621
  playout_urls.embed_url = embed_url;
351
622
  status.playout_urls = playout_urls;
352
- case 128:
353
- _context2.next = 133;
354
- break;
355
623
  case 130:
356
- _context2.prev = 130;
357
- _context2.t6 = _context2["catch"](5);
358
- console.error(_context2.t6);
359
- case 133:
360
- return _context2.abrupt("return", status);
361
- case 134:
624
+ _context3.next = 135;
625
+ break;
626
+ case 132:
627
+ _context3.prev = 132;
628
+ _context3.t6 = _context3["catch"](5);
629
+ console.error(_context3.t6);
630
+ case 135:
631
+ return _context3.abrupt("return", status);
632
+ case 136:
362
633
  case "end":
363
- return _context2.stop();
634
+ return _context3.stop();
364
635
  }
365
- }, _callee2, this, [[5, 130], [58, 69], [81, 91]]);
636
+ }, _callee3, this, [[5, 132], [60, 71], [83, 93]]);
366
637
  }));
367
- return function (_x2) {
368
- return _ref4.apply(this, arguments);
638
+ return function (_x3) {
639
+ return _ref6.apply(this, arguments);
369
640
  };
370
641
  }();
371
642
 
372
- // async StatusPrep({name}) {
373
- //
374
- // let conf = await this.LoadConf({name});
375
- //
376
- // try {
377
- //
378
- // // Set static token - avoid individual auth for separate channels/streams
379
- // let token = await MakeTxLessToken({client: this.client, libraryId: conf.libraryId});
380
- // this.client.SetStaticToken({token});
381
- //
382
- // } catch(error) {
383
- // console.log("StatusPrep failed: ", error);
384
- // return null;
385
- // }
386
- //
387
- // }
388
-
389
643
  /**
390
644
  * Create a new edge write token
391
645
  *
392
646
  * @methodGroup Live Stream
393
647
  * @namedParams
394
- * @param {string} name -
395
- * @param {boolean} start -
648
+ * @param {string} name - Object ID or name of the live stream object
649
+ * @param {boolean=} start - If specified, will start the stream after creation
396
650
  *
397
- * @return {Object} - The status response for the object
651
+ * @return {Promise<Object>} - The status response for the object
398
652
  *
399
653
  */
400
654
  exports.StreamCreate = /*#__PURE__*/function () {
401
- var _ref6 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee3(_ref5) {
402
- var name, _ref5$start, start, status, objectId, libraryId, liveRecording, fabURI, response, edgeToken, writeToken, objectHash;
403
- return _regeneratorRuntime.wrap(function _callee3$(_context3) {
404
- while (1) switch (_context3.prev = _context3.next) {
655
+ var _ref8 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee4(_ref7) {
656
+ var name, _ref7$start, start, status, objectId, libraryId, liveRecording, fabURI, response, edgeToken, writeToken, objectHash;
657
+ return _regeneratorRuntime.wrap(function _callee4$(_context4) {
658
+ while (1) switch (_context4.prev = _context4.next) {
405
659
  case 0:
406
- name = _ref5.name, _ref5$start = _ref5.start, start = _ref5$start === void 0 ? false : _ref5$start;
407
- _context3.next = 3;
660
+ name = _ref7.name, _ref7$start = _ref7.start, start = _ref7$start === void 0 ? false : _ref7$start;
661
+ _context4.next = 3;
408
662
  return this.StreamStatus({
409
663
  name: name
410
664
  });
411
665
  case 3:
412
- status = _context3.sent;
666
+ status = _context4.sent;
413
667
  if (!(status.state !== "inactive" && status.state !== "terminated" && status.state !== "stopped")) {
414
- _context3.next = 6;
668
+ _context4.next = 6;
415
669
  break;
416
670
  }
417
- return _context3.abrupt("return", {
671
+ return _context4.abrupt("return", {
418
672
  state: status.state,
419
673
  error: "stream still active - must terminate first"
420
674
  });
421
675
  case 6:
422
676
  objectId = status.object_id;
423
677
  console.log("START: ", name, "start", start);
424
- _context3.next = 10;
678
+ _context4.next = 10;
425
679
  return this.ContentObjectLibraryId({
426
680
  objectId: objectId
427
681
  });
428
682
  case 10:
429
- libraryId = _context3.sent;
430
- _context3.next = 13;
683
+ libraryId = _context4.sent;
684
+ _context4.next = 13;
431
685
  return this.ContentObjectMetadata({
432
686
  libraryId: libraryId,
433
687
  objectId: objectId,
434
688
  metadataSubtree: "/live_recording"
435
689
  });
436
690
  case 13:
437
- liveRecording = _context3.sent;
691
+ liveRecording = _context4.sent;
438
692
  fabURI = liveRecording.fabric_config.ingress_node_api; // Support both hostname and URL ingress_node_api
439
693
  if (!fabURI.startsWith("http")) {
440
694
  // Assume https
@@ -444,29 +698,29 @@ exports.StreamCreate = /*#__PURE__*/function () {
444
698
  fabricURIs: [fabURI]
445
699
  });
446
700
  console.log("Node URI", fabURI, "ID", liveRecording.fabric_config.ingress_node_id);
447
- _context3.next = 20;
701
+ _context4.next = 20;
448
702
  return this.EditContentObject({
449
703
  libraryId: libraryId,
450
704
  objectId: objectId
451
705
  });
452
706
  case 20:
453
- response = _context3.sent;
707
+ response = _context4.sent;
454
708
  edgeToken = response.write_token;
455
709
  console.log("Edge token:", edgeToken);
456
710
 
457
711
  /*
458
712
  * Set the metadata, including the edge token.
459
713
  */
460
- _context3.next = 25;
714
+ _context4.next = 25;
461
715
  return this.EditContentObject({
462
716
  libraryId: libraryId,
463
717
  objectId: objectId
464
718
  });
465
719
  case 25:
466
- response = _context3.sent;
720
+ response = _context4.sent;
467
721
  writeToken = response.write_token;
468
722
  this.Log("Merging metadata: ", libraryId, objectId, writeToken);
469
- _context3.next = 30;
723
+ _context4.next = 30;
470
724
  return this.MergeMetadata({
471
725
  libraryId: libraryId,
472
726
  objectId: objectId,
@@ -486,7 +740,7 @@ exports.StreamCreate = /*#__PURE__*/function () {
486
740
  });
487
741
  case 30:
488
742
  this.Log("Finalizing content draft: ", libraryId, objectId, writeToken);
489
- _context3.next = 33;
743
+ _context4.next = 33;
490
744
  return this.FinalizeContentObject({
491
745
  libraryId: libraryId,
492
746
  objectId: objectId,
@@ -494,7 +748,7 @@ exports.StreamCreate = /*#__PURE__*/function () {
494
748
  commitMessage: "Create stream edge write token " + edgeToken
495
749
  });
496
750
  case 33:
497
- response = _context3.sent;
751
+ response = _context4.sent;
498
752
  objectHash = response.hash;
499
753
  this.Log("Finalized object: ", objectHash);
500
754
  status = {
@@ -512,15 +766,15 @@ exports.StreamCreate = /*#__PURE__*/function () {
512
766
  op: start
513
767
  });
514
768
  }
515
- return _context3.abrupt("return", status);
769
+ return _context4.abrupt("return", status);
516
770
  case 39:
517
771
  case "end":
518
- return _context3.stop();
772
+ return _context4.stop();
519
773
  }
520
- }, _callee3, this);
774
+ }, _callee4, this);
521
775
  }));
522
- return function (_x3) {
523
- return _ref6.apply(this, arguments);
776
+ return function (_x4) {
777
+ return _ref8.apply(this, arguments);
524
778
  };
525
779
  }();
526
780
 
@@ -529,50 +783,48 @@ exports.StreamCreate = /*#__PURE__*/function () {
529
783
  *
530
784
  * @methodGroup Live Stream
531
785
  * @namedParams
532
- * @param {string} name -
533
- * @param {string=} op - The operation to perform. Possible values:
786
+ * @param {string} name - Object ID or name of the live stream object
787
+ * @param {string} op - The operation to perform. Possible values:
534
788
  * 'start'
535
789
  * 'reset' - Stops current LRO recording and starts a new one. Does
536
790
  * not create a new edge write token (just creates a new recording
537
791
  * period in the existing edge write token)
538
792
  * - 'stop'
539
793
  *
540
- * @return {Object} - The status response for the stream
794
+ * @return {Promise<Object>} - The status response for the stream
541
795
  *
542
796
  */
543
797
  exports.StreamStartOrStopOrReset = /*#__PURE__*/function () {
544
- var _ref8 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee4(_ref7) {
798
+ var _ref10 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee5(_ref9) {
545
799
  var name, op, status, _tries, tries;
546
- return _regeneratorRuntime.wrap(function _callee4$(_context4) {
547
- while (1) switch (_context4.prev = _context4.next) {
800
+ return _regeneratorRuntime.wrap(function _callee5$(_context5) {
801
+ while (1) switch (_context5.prev = _context5.next) {
548
802
  case 0:
549
- name = _ref7.name, op = _ref7.op;
550
- _context4.prev = 1;
551
- console.log("Stream ", op, ": ", name);
552
- _context4.next = 5;
803
+ name = _ref9.name, op = _ref9.op;
804
+ _context5.prev = 1;
805
+ _context5.next = 4;
553
806
  return this.StreamStatus({
554
807
  name: name
555
808
  });
556
- case 5:
557
- status = _context4.sent;
809
+ case 4:
810
+ status = _context5.sent;
558
811
  if (!(status.state != "stopped")) {
559
- _context4.next = 10;
812
+ _context5.next = 9;
560
813
  break;
561
814
  }
562
815
  if (!(op === "start")) {
563
- _context4.next = 10;
816
+ _context5.next = 9;
564
817
  break;
565
818
  }
566
819
  status.error = "Unable to start stream - state: " + status.state;
567
- return _context4.abrupt("return", status);
568
- case 10:
820
+ return _context5.abrupt("return", status);
821
+ case 9:
569
822
  if (!(status.state == "running" || status.state == "starting" || status.state == "stalled")) {
570
- _context4.next = 33;
823
+ _context5.next = 31;
571
824
  break;
572
825
  }
573
- console.log("STOPPING");
574
- _context4.prev = 12;
575
- _context4.next = 15;
826
+ _context5.prev = 10;
827
+ _context5.next = 13;
576
828
  return this.CallBitcodeMethod({
577
829
  libraryId: status.library_id,
578
830
  objectId: status.object_id,
@@ -580,50 +832,50 @@ exports.StreamStartOrStopOrReset = /*#__PURE__*/function () {
580
832
  method: "/live/stop/" + status.tlro,
581
833
  constant: false
582
834
  });
583
- case 15:
584
- _context4.next = 19;
835
+ case 13:
836
+ _context5.next = 17;
585
837
  break;
838
+ case 15:
839
+ _context5.prev = 15;
840
+ _context5.t0 = _context5["catch"](10);
586
841
  case 17:
587
- _context4.prev = 17;
588
- _context4.t0 = _context4["catch"](12);
589
- case 19:
590
842
  // Wait until LRO is terminated
591
843
  _tries = 10;
592
- case 20:
844
+ case 18:
593
845
  if (!(status.state != "stopped" && _tries-- > 0)) {
594
- _context4.next = 29;
846
+ _context5.next = 27;
595
847
  break;
596
848
  }
597
849
  console.log("Wait to terminate - ", status.state);
598
- _context4.next = 24;
599
- return sleep(1000);
600
- case 24:
601
- _context4.next = 26;
850
+ _context5.next = 22;
851
+ return Sleep(1000);
852
+ case 22:
853
+ _context5.next = 24;
602
854
  return this.StreamStatus({
603
855
  name: name
604
856
  });
605
- case 26:
606
- status = _context4.sent;
607
- _context4.next = 20;
857
+ case 24:
858
+ status = _context5.sent;
859
+ _context5.next = 18;
608
860
  break;
609
- case 29:
610
- console.log("Status after terminate - ", status.state);
861
+ case 27:
862
+ console.log("Status after stop - ", status.state);
611
863
  if (!(_tries <= 0)) {
612
- _context4.next = 33;
864
+ _context5.next = 31;
613
865
  break;
614
866
  }
615
- console.log("Failed to terminate");
616
- return _context4.abrupt("return", status);
617
- case 33:
867
+ console.log("Failed to stop");
868
+ return _context5.abrupt("return", status);
869
+ case 31:
618
870
  if (!(op === "stop")) {
619
- _context4.next = 35;
871
+ _context5.next = 33;
620
872
  break;
621
873
  }
622
- return _context4.abrupt("return", status);
623
- case 35:
874
+ return _context5.abrupt("return", status);
875
+ case 33:
624
876
  console.log("STARTING", "edge_write_token", status.edge_write_token);
625
- _context4.prev = 36;
626
- _context4.next = 39;
877
+ _context5.prev = 34;
878
+ _context5.next = 37;
627
879
  return this.CallBitcodeMethod({
628
880
  libraryId: status.library_id,
629
881
  objectId: status.object_id,
@@ -631,734 +883,803 @@ exports.StreamStartOrStopOrReset = /*#__PURE__*/function () {
631
883
  method: "/live/start",
632
884
  constant: false
633
885
  });
634
- case 39:
635
- _context4.next = 45;
886
+ case 37:
887
+ _context5.next = 43;
636
888
  break;
637
- case 41:
638
- _context4.prev = 41;
639
- _context4.t1 = _context4["catch"](36);
640
- console.log("LRO Start (failed): ", _context4.t1);
641
- return _context4.abrupt("return", {
889
+ case 39:
890
+ _context5.prev = 39;
891
+ _context5.t1 = _context5["catch"](34);
892
+ console.log("LRO Start (failed): ", _context5.t1);
893
+ return _context5.abrupt("return", {
642
894
  state: status.state,
643
895
  error: "LRO start failed - must create a stream first"
644
896
  });
645
- case 45:
897
+ case 43:
646
898
  // Wait until LRO is 'starting'
647
899
  tries = 10;
648
- case 46:
900
+ case 44:
649
901
  if (!(status.state != "starting" && tries-- > 0)) {
650
- _context4.next = 55;
902
+ _context5.next = 53;
651
903
  break;
652
904
  }
653
905
  console.log("Wait to start - ", status.state);
654
- _context4.next = 50;
655
- return sleep(1000);
656
- case 50:
657
- _context4.next = 52;
906
+ _context5.next = 48;
907
+ return Sleep(1000);
908
+ case 48:
909
+ _context5.next = 50;
658
910
  return this.StreamStatus({
659
911
  name: name
660
912
  });
661
- case 52:
662
- status = _context4.sent;
663
- _context4.next = 46;
913
+ case 50:
914
+ status = _context5.sent;
915
+ _context5.next = 44;
664
916
  break;
665
- case 55:
917
+ case 53:
666
918
  console.log("Status after restart - ", status.state);
667
- return _context4.abrupt("return", status);
668
- case 59:
669
- _context4.prev = 59;
670
- _context4.t2 = _context4["catch"](1);
671
- console.error(_context4.t2);
672
- case 62:
673
- case "end":
674
- return _context4.stop();
675
- }
676
- }, _callee4, this, [[1, 59], [12, 17], [36, 41]]);
677
- }));
678
- return function (_x4) {
679
- return _ref8.apply(this, arguments);
680
- };
681
- }();
682
-
683
- /*
684
- * Stop the live stream session and close the edge write token.
685
- * Not implemented fully
686
- */
687
- // async StopSession({name}) {
688
- //
689
- // try {
690
- //
691
- // console.log("TERMINATE: ", name);
692
- //
693
- // let conf = await this.LoadConf({name});
694
- //
695
- // let objectId = conf.objectId;
696
- // let libraryId = await this.client.ContentObjectLibraryId({objectId: objectId});
697
- //
698
- // let mainMeta = await this.client.ContentObjectMetadata({
699
- // libraryId: libraryId,
700
- // objectId: objectId
701
- // });
702
- //
703
- // let fabURI = mainMeta.live_recording.fabric_config.ingress_node_api;
704
- // // Support both hostname and URL ingress_node_api
705
- // if(!fabURI.startsWith("http")) {
706
- // // Assume https
707
- // fabURI = "https://" + fabURI;
708
- // }
709
- //
710
- // this.client.SetNodes({fabricURIs: [fabURI]});
711
- //
712
- // let edgeWriteToken = mainMeta.live_recording.fabric_config.edge_write_token;
713
- //
714
- // if(edgeWriteToken === undefined || edgeWriteToken === "") {
715
- // return {
716
- // state: "inactive",
717
- // error: "no active streams - must create a stream first"
718
- // };
719
- // }
720
- // let edgeMeta = await this.client.ContentObjectMetadata({
721
- // libraryId: libraryId,
722
- // objectId: objectId,
723
- // writeToken: edgeWriteToken
724
- // });
725
- //
726
- // // Stop the LRO if running
727
- // let status = await this.Status({name});
728
- // if(status.state != "terminated") {
729
- // console.log("STOPPING");
730
- // try {
731
- // await this.client.CallBitcodeMethod({
732
- // libraryId: status.library_id,
733
- // objectId: status.object_id,
734
- // writeToken: status.edge_write_token,
735
- // method: "/live/stop/" + status.tlro,
736
- // constant: false
737
- // });
738
- // } catch(error) {
739
- // // The /call/lro/stop API returns empty response
740
- // // console.log("LRO Stop (failed): ", error);
741
- // }
742
- //
743
- // // Wait until LRO is terminated
744
- // let tries = 10;
745
- // while (status.state != "terminated" && tries-- > 0) {
746
- // console.log("Wait to terminate - ", status.state);
747
- // await sleep(1000);
748
- // status = await this.Status({name});
749
- // }
750
- // console.log("Status after terminate - ", status.state);
751
- //
752
- // if(tries <= 0) {
753
- // console.log("Failed to terminate");
754
- // return status;
755
- // }
756
- // }
757
- //
758
- // // Set stop time
759
- // edgeMeta.recording_stop_time = Math.floor(new Date().getTime() / 1000);
760
- // console.log("recording_start_time: ", edgeMeta.recording_start_time);
761
- // console.log("recording_stop_time: ", edgeMeta.recording_stop_time);
762
- //
763
- // edgeMeta.live_recording.status = {
764
- // state: "terminated",
765
- // recording_stop_time: edgeMeta.recording_stop_time
766
- // };
767
- //
768
- // edgeMeta.live_recording.fabric_config.edge_write_token = "";
769
- //
770
- // await this.client.ReplaceMetadata({
771
- // libraryId: libraryId,
772
- // objectId: objectId,
773
- // writeToken: edgeWriteToken,
774
- // metadata: edgeMeta
775
- // });
776
- //
777
- // let fin = await this.client.FinalizeContentObject({
778
- // libraryId,
779
- // objectId,
780
- // writeToken: edgeWriteToken,
781
- // commitMessage: "Finalize live stream - stop time " + edgeMeta.recording_stop_time,
782
- // publish: false // Don't publish this version because it is not currently useful
783
- // });
784
- //
785
- // return {
786
- // fin,
787
- // name: name,
788
- // edge_write_token: edgeWriteToken,
789
- // state: "terminated"
790
- // };
791
- //
792
- // } catch(error) {
793
- // console.error(error);
794
- // }
795
- // }
796
-
797
- // async Initialize({name, drm=false, format}) {
798
- //
799
- // const contentTypes = await this.client.ContentTypes();
800
- //
801
- // let typeAbrMaster;
802
- // let typeLiveStream;
803
- // for (let i = 0; i < Object.keys(contentTypes).length; i ++) {
804
- // const key = Object.keys(contentTypes)[i];
805
- // if(contentTypes[key].name.includes("ABR Master") || contentTypes[key].name.includes("Title")) {
806
- // typeAbrMaster = contentTypes[key].hash;
807
- // }
808
- // if(contentTypes[key].name.includes("Live Stream")) {
809
- // typeLiveStream = contentTypes[key].hash;
810
- // }
811
- // }
812
- //
813
- // if(typeAbrMaster === undefined || typeLiveStream === undefined) {
814
- // console.log("ERROR - unable to find content types", "ABR Master", typeAbrMaster, "Live Stream", typeLiveStream);
815
- // return {};
816
- // }
817
- // let res = await this.SetOfferingAndDRM({name, typeAbrMaster, typeLiveStream, drm, format});
818
- // return res;
819
- // }
820
-
821
- // async SetOfferingAndDRM({name, typeAbrMaster, typeLiveStream, drm=false, format}) {
822
- //
823
- // let status = await this.Status({name});
824
- // if(status.state != "inactive" && status.state != "terminated") {
825
- // return {
826
- // state: status.state,
827
- // error: "stream still active - must terminate first"
828
- // };
829
- // }
830
- //
831
- // let objectId = status.object_id;
832
- //
833
- // console.log("INIT: ", name, objectId);
834
- //
835
- // const {GenerateOffering} = require("./LiveObjectSetupStepOne");
836
- //
837
- // const aBitRate = 128000;
838
- // const aChannels = 2;
839
- // const aSampleRate = 48000;
840
- // const aStreamIndex = 1;
841
- // const aTimeBase = "1/48000";
842
- // const aChannelLayout = "stereo";
843
- //
844
- // const vBitRate = 14000000;
845
- // const vHeight = 720;
846
- // const vStreamIndex = 0;
847
- // const vWidth = 1280;
848
- // const vDisplayAspectRatio = "16/9";
849
- // const vFrameRate = "30000/1001";
850
- // const vTimeBase = "1/30000"; // "1/16000";
851
- //
852
- // const abrProfile = require("./abr_profile_live_drm.json");
853
- //
854
- // let playoutFormats = abrProfile.playout_formats;
855
- // if(format) {
856
- // drm = true; // Override DRM parameter
857
- // playoutFormats = {};
858
- // let formats = format.split(",");
859
- // for (let i = 0; i < formats.length; i++) {
860
- // if(formats[i] === "hls-clear") {
861
- // abrProfile.drm_optional = true;
862
- // playoutFormats["hls-clear"] = {
863
- // "drm": null,
864
- // "protocol": {
865
- // "type": "ProtoHls"
866
- // }
867
- // };
868
- // continue;
869
- // }
870
- // playoutFormats[formats[i]] = abrProfile.playout_formats[formats[i]];
871
- // }
872
- // } else if(!drm) {
873
- // abrProfile.drm_optional = true;
874
- // playoutFormats = {
875
- // "hls-clear": {
876
- // "drm": null,
877
- // "protocol": {
878
- // "type": "ProtoHls"
879
- // }
880
- // }
881
- // };
882
- // }
883
- //
884
- // abrProfile.playout_formats = playoutFormats;
885
- //
886
- // let libraryId = await this.client.ContentObjectLibraryId({objectId});
887
- //
888
- // try {
889
- //
890
- // let mainMeta = await this.client.ContentObjectMetadata({
891
- // libraryId: libraryId,
892
- // objectId: objectId
893
- // });
894
- //
895
- // let fabURI = mainMeta.live_recording.fabric_config.ingress_node_api;
896
- // // Support both hostname and URL ingress_node_api
897
- // if(!fabURI.startsWith("http")) {
898
- // // Assume https
899
- // fabURI = "https://" + fabURI;
900
- // }
901
- //
902
- // this.client.SetNodes({fabricURIs: [fabURI]});
903
- //
904
- // let streamUrl = mainMeta.live_recording.recording_config.recording_params.origin_url;
905
- //
906
- // await GenerateOffering({
907
- // client: this.client,
908
- // libraryId,
909
- // objectId,
910
- // typeAbrMaster, typeLiveStream,
911
- // streamUrl,
912
- // abrProfile,
913
- // aBitRate, aChannels, aSampleRate, aStreamIndex,
914
- // aTimeBase,
915
- // aChannelLayout,
916
- // vBitRate, vHeight, vStreamIndex, vWidth,
917
- // vDisplayAspectRatio, vFrameRate, vTimeBase
918
- // });
919
- //
920
- // console.log("GenerateOffering - DONE");
921
- //
922
- // return {
923
- // name,
924
- // object_id: objectId,
925
- // state: "initialized"
926
- // };
927
- // } catch(error) {
928
- // console.error(error);
929
- // }
930
- // }
931
-
932
- // Add a content insertion entry
933
- // Parameters:
934
- // - insertionTime - seconds (float)
935
- // - sinceStart - true if time specified since stream start, false if since epoch
936
- // - duration - seconds (float, deafault 20.0)
937
- // - targetHash - playable
938
- // - remove - flag to remove the insertion at that exact 'time' (instead of adding)
939
- // async Insertion({name, insertionTime, sinceStart, duration, targetHash, remove}) {
940
- //
941
- // // Determine audio and video parameters of the insertion
942
- // const insertionInfo = await this.getOfferingInfo({versionHash: targetHash});
943
- // const audioAbrDuration = insertionInfo.audio.seg_duration_sec;
944
- // const videoAbrDuration = insertionInfo.video.seg_duration_sec;
945
- //
946
- // if(audioAbrDuration === 0 || videoAbrDuration === 0) {
947
- // throw new Error("Bad segment duration hash:", targetHash);
948
- // }
949
- //
950
- // if(duration === undefined) {
951
- // duration = insertionInfo.duration_sec; // Use full duration of the insertion
952
- // } else {
953
- // if(duration > insertionInfo.duration_sec) {
954
- // throw new Error("Bad duration - larger than insertion object duration", insertionInfo.duration_sec);
955
- // }
956
- // }
957
- //
958
- // let conf = await this.LoadConf({name});
959
- // let libraryId = await this.client.ContentObjectLibraryId({objectId: conf.objectId});
960
- // let objectId = conf.objectId;
961
- //
962
- // let mainMeta = await this.client.ContentObjectMetadata({
963
- // libraryId: libraryId,
964
- // objectId: conf.objectId
965
- // });
966
- //
967
- // let fabURI = mainMeta.live_recording.fabric_config.ingress_node_api;
968
- //
969
- // // Support both hostname and URL ingress_node_api
970
- // if(!fabURI.startsWith("http")) {
971
- // // Assume https
972
- // fabURI = "https://" + fabURI;
973
- // }
974
- // this.client.SetNodes({fabricURIs: [fabURI]});
975
- // let edgeWriteToken = mainMeta.live_recording.fabric_config.edge_write_token;
976
- //
977
- // let edgeMeta = await this.client.ContentObjectMetadata({
978
- // libraryId: libraryId,
979
- // objectId: conf.objectId,
980
- // writeToken: edgeWriteToken
981
- // });
982
- //
983
- // // Find stream start time (from the most recent recording section)
984
- // let recordings = edgeMeta.live_recording.recordings;
985
- // let sequence = 1;
986
- // let streamStartTime = 0;
987
- // if(recordings != undefined && recordings.recording_sequence != undefined) {
988
- // // We have at least one recording - check if still active
989
- // sequence = recordings.recording_sequence;
990
- // let period = recordings.live_offering[sequence - 1];
991
- //
992
- // if(period.end_time_epoch_sec > 0) {
993
- // // The last period is closed - apply insertions to the next period
994
- // sequence ++;
995
- // } else {
996
- // // The period is active
997
- // streamStartTime = period.start_time_epoch_sec;
998
- // }
999
- // }
1000
- //
1001
- // if(streamStartTime === 0) {
1002
- // // There is no active period - must use absolute time
1003
- // if(sinceStart === false) {
1004
- // throw new Error("Stream not running - must use 'time since start'");
1005
- // }
1006
- // }
1007
- //
1008
- // // Find the current period playout configuration
1009
- // if(edgeMeta.live_recording.playout_config.interleaves === undefined) {
1010
- // edgeMeta.live_recording.playout_config.interleaves = {};
1011
- // }
1012
- // if(edgeMeta.live_recording.playout_config.interleaves[sequence] === undefined) {
1013
- // edgeMeta.live_recording.playout_config.interleaves[sequence] = [];
1014
- // }
1015
- //
1016
- // let playoutConfig = edgeMeta.live_recording.playout_config;
1017
- // let insertions = playoutConfig.interleaves[sequence];
1018
- //
1019
- // let res = {};
1020
- //
1021
- // if(!sinceStart) {
1022
- // insertionTime = insertionTime - streamStartTime;
1023
- // }
1024
- //
1025
- // // Assume insertions are sorted by insertion time
1026
- // let errs = [];
1027
- // let currentTime = -1;
1028
- // let insertionDone = false;
1029
- // let newInsertion = {
1030
- // insertion_time: insertionTime,
1031
- // duration: duration,
1032
- // audio_abr_duration: audioAbrDuration,
1033
- // video_abr_duration: videoAbrDuration,
1034
- // playout: "/qfab/" + targetHash + "/rep/playout" // TO FIX - should be a link
1035
- // };
1036
- //
1037
- // for (let i = 0; i < insertions.length; i ++) {
1038
- // if(insertions[i].insertion_time <= currentTime) {
1039
- // // Bad insertion - must be later than current time
1040
- // append(errs, "Bad insertion - time:", insertions[i].insertion_time);
1041
- // }
1042
- // if(remove) {
1043
- // if(insertions[i].insertion_time === insertionTime) {
1044
- // insertions.splice(i, 1);
1045
- // break;
1046
- // }
1047
- // } else {
1048
- // if(insertions[i].insertion_time > insertionTime) {
1049
- // if(i > 0) {
1050
- // insertions = [
1051
- // ...insertions.splice(0, i),
1052
- // newInsertion,
1053
- // ...insertions.splice(i)
1054
- // ];
1055
- // } else {
1056
- // insertions = [
1057
- // newInsertion,
1058
- // ...insertions.splice(i)
1059
- // ];
1060
- // }
1061
- // insertionDone = true;
1062
- // break;
1063
- // }
1064
- // }
1065
- // }
1066
- //
1067
- // if(!remove && !insertionDone) {
1068
- // // Add to the end of the insertions list
1069
- // console.log("Add insertion at the end");
1070
- // insertions = [
1071
- // ...insertions,
1072
- // newInsertion
1073
- // ];
1074
- // }
1075
- //
1076
- // playoutConfig.interleaves[sequence] = insertions;
1077
- //
1078
- // // Store the new insertions in the write token
1079
- // await this.client.ReplaceMetadata({
1080
- // libraryId: libraryId,
1081
- // objectId: objectId,
1082
- // writeToken: edgeWriteToken,
1083
- // metadataSubtree: "/live_recording/playout_config",
1084
- // metadata: edgeMeta.live_recording.playout_config
1085
- // });
1086
- //
1087
- // res.errors = errs;
1088
- // res.insertions = insertions;
1089
- // return res;
1090
- // }
1091
-
1092
- exports.LoadConf = /*#__PURE__*/function () {
1093
- var _ref10 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee5(_ref9) {
1094
- var name, streamsBuf, streams, conf;
1095
- return _regeneratorRuntime.wrap(function _callee5$(_context5) {
1096
- while (1) switch (_context5.prev = _context5.next) {
1097
- case 0:
1098
- name = _ref9.name;
1099
- if (!name.startsWith("iq__")) {
1100
- _context5.next = 3;
1101
- break;
1102
- }
1103
- return _context5.abrupt("return", {
1104
- name: name,
1105
- objectId: name
1106
- });
1107
- case 3:
1108
- _context5.prev = 3;
1109
- streamsBuf = fs.readFileSync(path.resolve(__dirname, "../liveconf.json"));
1110
- _context5.next = 11;
1111
- break;
1112
- case 7:
1113
- _context5.prev = 7;
1114
- _context5.t0 = _context5["catch"](3);
1115
- console.log("Stream name must be a QID or a label in liveconf.json");
1116
- return _context5.abrupt("return", {});
1117
- case 11:
1118
- streams = JSON.parse(streamsBuf);
1119
- conf = streams[name];
1120
- if (!(conf === null)) {
1121
- _context5.next = 16;
1122
- break;
1123
- }
1124
- console.log("Bad name: ", name);
1125
- return _context5.abrupt("return", {});
1126
- case 16:
1127
- return _context5.abrupt("return", conf);
1128
- case 17:
919
+ return _context5.abrupt("return", status);
920
+ case 57:
921
+ _context5.prev = 57;
922
+ _context5.t2 = _context5["catch"](1);
923
+ console.error(_context5.t2);
924
+ case 60:
1129
925
  case "end":
1130
926
  return _context5.stop();
1131
927
  }
1132
- }, _callee5, null, [[3, 7]]);
928
+ }, _callee5, this, [[1, 57], [10, 15], [34, 39]]);
1133
929
  }));
1134
930
  return function (_x5) {
1135
931
  return _ref10.apply(this, arguments);
1136
932
  };
1137
933
  }();
1138
934
 
1139
- /*
1140
- * Read a playable contnet object and get information about a particular offering
1141
- */
1142
- // async getOfferingInfo({versionHash, offering = "default"}) {
1143
- //
1144
- // // Content Type check is currently disabled due to permissions
1145
- // /*
1146
- // let ct = await this.client.ContentObject({versionHash});
1147
- // if(ct.type != undefined && ct.type != "") {
1148
- // let typeMeta = await this.client.ContentObjectMetadata({
1149
- // versionHash: ct.type
1150
- // });
1151
- // if(typeMeta.bitcode_flags != "abrmaster") {
1152
- // throw new Error("Not a playable VoD object " + versionHash);
1153
- // }
1154
- // }
1155
- // */
1156
- // let offeringMeta = await this.client.ContentObjectMetadata({
1157
- // versionHash,
1158
- // metadataSubtree: "/offerings/" + offering
1159
- // });
1160
- //
1161
- // var info = {
1162
- // duration_sec: 0 // Minimum of video and audio duration
1163
- // };
1164
- // ["video", "audio"].forEach(mt => {
1165
- // const stream = offeringMeta.media_struct.streams[mt];
1166
- // info[mt] = {
1167
- // seg_duration_sec: stream.optimum_seg_dur.float,
1168
- // duration_sec: stream.duration.float,
1169
- // frame_rate_rat: stream.rate,
1170
- // };
1171
- // if(info.duration_sec === 0 || stream.duration.float < info.duration_sec) {
1172
- // info.duration_sec = stream.duration.float;
1173
- // }
1174
- // });
1175
- // return info;
1176
- // }
1177
-
1178
- // async StreamDownload({name, period}) {
1179
- //
1180
- // let conf = await this.LoadConf({name});
1181
- //
1182
- // let status = {name};
1183
- //
1184
- // try {
1185
- //
1186
- // let libraryId = await this.client.ContentObjectLibraryId({objectId: conf.objectId});
1187
- // status.library_id = libraryId;
1188
- // status.object_id = conf.objectId;
1189
- //
1190
- // let mainMeta = await this.client.ContentObjectMetadata({
1191
- // libraryId: libraryId,
1192
- // objectId: conf.objectId
1193
- // });
1194
- //
1195
- // let fabURI = mainMeta.live_recording.fabric_config.ingress_node_api;
1196
- // if(fabURI === undefined) {
1197
- // console.log("bad fabric config - missing ingress node API");
1198
- // }
1199
- //
1200
- // // Support both hostname and URL ingress_node_api
1201
- // if(!fabURI.startsWith("http")) {
1202
- // // Assume https
1203
- // fabURI = "https://" + fabURI;
1204
- // }
1205
- // this.client.SetNodes({fabricURIs: [fabURI]});
1206
- //
1207
- // let edgeWriteToken = mainMeta.live_recording.fabric_config.edge_write_token;
1208
- // let edgeMeta = await this.client.ContentObjectMetadata({
1209
- // libraryId: libraryId,
1210
- // objectId: conf.objectId,
1211
- // writeToken: edgeWriteToken
1212
- // });
1213
- //
1214
- // // If a stream has never been started return state 'inactive'
1215
- // if(edgeMeta.live_recording === undefined ||
1216
- // edgeMeta.live_recording.recordings === undefined ||
1217
- // edgeMeta.live_recording.recordings.recording_sequence === undefined) {
1218
- // status.state = "no recordings";
1219
- // return status;
1220
- // }
1221
- //
1222
- // let recordings = edgeMeta.live_recording.recordings;
1223
- // status.recording_period_sequence = recordings.recording_sequence;
1224
- //
1225
- // let sequence = recordings.recording_sequence;
1226
- // if(period === undefined || period < 0 || period > sequence - 1) {
1227
- // period = sequence - 1;
1228
- // }
1229
- //
1230
- // console.log("Downloading stream", name, " period", period, " latest", sequence - 1);
1231
- //
1232
- // let recording = recordings.live_offering[period];
1233
- // if(recording === undefined) {
1234
- // console.log("ERROR - recording period not found: ", period);
1235
- // }
1236
- //
1237
- // let dpath = "DOWNLOAD/" + edgeWriteToken + "." + period;
1238
- // !fs.existsSync(dpath) && fs.mkdirSync(dpath, {recursive: true});
1239
- //
1240
- // let mts = ["audio", "video"];
1241
- // for (let mi = 0; mi < mts.length; mi ++) {
1242
- // let mt = mts[mi];
1243
- // console.log("Downloading ", mt);
1244
- // let mtpath = dpath + "/" + mt;
1245
- // let partsfile = dpath + "/parts_" + mt + ".txt";
1246
- // !fs.existsSync(mtpath) && fs.mkdirSync(mtpath);
1247
- // var sources = recording.sources[mt];
1248
- // for (let i = 0; i < sources.length - 1; i++) {
1249
- // console.log(sources[i].hash);
1250
- // let partHash = sources[i].hash;
1251
- // let buf = await this.client.DownloadPart({
1252
- // libraryId,
1253
- // objectId: conf.objectId,
1254
- // partHash,
1255
- // format: "buffer",
1256
- // chunked: false,
1257
- // callback: ({bytesFinished, bytesTotal}) => {
1258
- // console.log(" progress: ", bytesFinished + "/" + bytesTotal);
1259
- // }
1260
- // });
1261
- //
1262
- // let partfile = mtpath + "/" + partHash + ".mp4";
1263
- // fs.appendFile(partfile, buf, (err) => {
1264
- // if(err)
1265
- // console.log(err);
1266
- // });
1267
- // fs.appendFile(partsfile, "file '" + mt + "/" + partHash + ".mp4'\n", (err) => {
1268
- // if(err)
1269
- // console.log(err);
1270
- // });
1271
- // }
1272
- //
1273
- // // Concatenate parts into one mp4
1274
- // let cmd = "ffmpeg -f concat -safe 0 -i " + partsfile + " -c copy " + dpath + "/" + mt + ".mp4";
1275
- // console.log("Running", cmd);
1276
- // execSync(cmd);
1277
- // }
1278
- //
1279
- // // Create final mp4 file
1280
- // let f = dpath + "/download.mp4";
1281
- // let cmd = "ffmpeg -i " + dpath + "/video.mp4" + " -i " + dpath + "/audio.mp4" + " -map 0:v:0 -map 1:a:0 -c copy -shortest " + f;
1282
- // console.log("Running", cmd);
1283
- // execSync(cmd);
1284
- //
1285
- // status.file = f;
1286
- // status.state = "completed";
1287
- // } catch(e) {
1288
- // console.log("Download failed", e);
1289
- // throw e;
1290
- // }
1291
- //
1292
- // return status;
1293
- // }
1294
-
1295
935
  /**
1296
- * Configure the stream
936
+ * Stop the live stream session and close the edge write token.
937
+ * Not implemented fully
1297
938
  *
1298
939
  * @methodGroup Live Stream
1299
940
  * @namedParams
1300
- * @param {string} name -
1301
- * @param {string=} op - The operation to perform. Possible values:
1302
- * 'start'
1303
- * 'reset' - Stops current LRO recording and starts a new one. Does
1304
- * not create a new edge write token (just creates a new recording
1305
- * period in the existing edge write token)
1306
- * - 'stop'
1307
- *
1308
- * @return {Object} - The status response for the stream
941
+ * @param {string} name - Object ID or name of the live stream object
1309
942
  *
943
+ * @return {Promise<Object>} - The finalize response for the stream object
1310
944
  */
1311
- exports.StreamConfig = /*#__PURE__*/function () {
945
+ exports.StreamStopSession = /*#__PURE__*/function () {
1312
946
  var _ref12 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee6(_ref11) {
1313
- var name, customSettings, conf, status, libraryId, mainMeta, userConfig, hostName, streamUrl, nodes, node, endpoint, probe, controller, timeoutId, probeUrl, lc, liveRecordingConfigStr, liveRecordingConfig, e, writeToken;
947
+ var name, conf, objectId, libraryId, mainMeta, fabURI, edgeWriteToken, edgeMeta, status, tries, fin;
1314
948
  return _regeneratorRuntime.wrap(function _callee6$(_context6) {
1315
949
  while (1) switch (_context6.prev = _context6.next) {
1316
950
  case 0:
1317
- name = _ref11.name, customSettings = _ref11.customSettings;
1318
- _context6.next = 3;
951
+ name = _ref11.name;
952
+ _context6.prev = 1;
953
+ console.log("TERMINATE: ", name);
954
+ _context6.next = 5;
1319
955
  return this.LoadConf({
1320
956
  name: name
1321
957
  });
1322
- case 3:
958
+ case 5:
1323
959
  conf = _context6.sent;
1324
- status = {
1325
- name: name
1326
- };
1327
- _context6.next = 7;
960
+ objectId = conf.objectId;
961
+ _context6.next = 9;
1328
962
  return this.ContentObjectLibraryId({
1329
- objectId: conf.objectId
963
+ objectId: objectId
1330
964
  });
1331
- case 7:
965
+ case 9:
1332
966
  libraryId = _context6.sent;
1333
- status.library_id = libraryId;
1334
- status.object_id = conf.objectId;
1335
967
  _context6.next = 12;
1336
968
  return this.ContentObjectMetadata({
1337
969
  libraryId: libraryId,
1338
- objectId: conf.objectId
970
+ objectId: objectId
1339
971
  });
1340
972
  case 12:
1341
973
  mainMeta = _context6.sent;
1342
- userConfig = mainMeta.live_recording_config;
1343
- status.user_config = userConfig;
1344
-
1345
- // Get node URI from user config
1346
- hostName = userConfig.url.replace("udp://", "").replace("rtmp://", "").split(":")[0];
1347
- streamUrl = new URL(userConfig.url);
1348
- console.log("Retrieving nodes...");
1349
- _context6.next = 20;
1350
- return this.SpaceNodes({
1351
- matchEndpoint: hostName
974
+ fabURI = mainMeta.live_recording.fabric_config.ingress_node_api; // Support both hostname and URL ingress_node_api
975
+ if (!fabURI.startsWith("http")) {
976
+ // Assume https
977
+ fabURI = "https://" + fabURI;
978
+ }
979
+ this.SetNodes({
980
+ fabricURIs: [fabURI]
1352
981
  });
1353
- case 20:
1354
- nodes = _context6.sent;
1355
- if (!(nodes.length < 1)) {
1356
- _context6.next = 24;
982
+ edgeWriteToken = mainMeta.live_recording.fabric_config.edge_write_token;
983
+ if (!(edgeWriteToken === undefined || edgeWriteToken === "")) {
984
+ _context6.next = 19;
1357
985
  break;
1358
986
  }
1359
- status.error = "No node matching stream URL " + streamUrl.href;
1360
- return _context6.abrupt("return", status);
1361
- case 24:
987
+ return _context6.abrupt("return", {
988
+ state: "inactive",
989
+ error: "no active streams - must create a stream first"
990
+ });
991
+ case 19:
992
+ _context6.next = 21;
993
+ return this.ContentObjectMetadata({
994
+ libraryId: libraryId,
995
+ objectId: objectId,
996
+ writeToken: edgeWriteToken
997
+ });
998
+ case 21:
999
+ edgeMeta = _context6.sent;
1000
+ _context6.next = 24;
1001
+ return this.StreamStatus({
1002
+ name: name
1003
+ });
1004
+ case 24:
1005
+ status = _context6.sent;
1006
+ if (!(status.state != "terminated")) {
1007
+ _context6.next = 48;
1008
+ break;
1009
+ }
1010
+ console.log("STOPPING");
1011
+ _context6.prev = 27;
1012
+ _context6.next = 30;
1013
+ return this.CallBitcodeMethod({
1014
+ libraryId: status.library_id,
1015
+ objectId: status.object_id,
1016
+ writeToken: status.edge_write_token,
1017
+ method: "/live/stop/" + status.tlro,
1018
+ constant: false
1019
+ });
1020
+ case 30:
1021
+ _context6.next = 34;
1022
+ break;
1023
+ case 32:
1024
+ _context6.prev = 32;
1025
+ _context6.t0 = _context6["catch"](27);
1026
+ case 34:
1027
+ // Wait until LRO is terminated
1028
+ tries = 10;
1029
+ case 35:
1030
+ if (!(status.state != "stopped" && tries-- > 0)) {
1031
+ _context6.next = 44;
1032
+ break;
1033
+ }
1034
+ console.log("Wait to terminate - ", status.state);
1035
+ _context6.next = 39;
1036
+ return Sleep(1000);
1037
+ case 39:
1038
+ _context6.next = 41;
1039
+ return this.StreamStatus({
1040
+ name: name
1041
+ });
1042
+ case 41:
1043
+ status = _context6.sent;
1044
+ _context6.next = 35;
1045
+ break;
1046
+ case 44:
1047
+ console.log("Status after stop - ", status.state);
1048
+ if (!(tries <= 0)) {
1049
+ _context6.next = 48;
1050
+ break;
1051
+ }
1052
+ console.log("Failed to stop");
1053
+ return _context6.abrupt("return", status);
1054
+ case 48:
1055
+ // Set stop time
1056
+ edgeMeta.recording_stop_time = Math.floor(new Date().getTime() / 1000);
1057
+ console.log("recording_start_time: ", edgeMeta.recording_start_time);
1058
+ console.log("recording_stop_time: ", edgeMeta.recording_stop_time);
1059
+ edgeMeta.live_recording.status = {
1060
+ state: "terminated",
1061
+ recording_stop_time: edgeMeta.recording_stop_time
1062
+ };
1063
+ edgeMeta.live_recording.fabric_config.edge_write_token = "";
1064
+ _context6.next = 55;
1065
+ return this.ReplaceMetadata({
1066
+ libraryId: libraryId,
1067
+ objectId: objectId,
1068
+ writeToken: edgeWriteToken,
1069
+ metadata: edgeMeta
1070
+ });
1071
+ case 55:
1072
+ _context6.next = 57;
1073
+ return this.FinalizeContentObject({
1074
+ libraryId: libraryId,
1075
+ objectId: objectId,
1076
+ writeToken: edgeWriteToken,
1077
+ commitMessage: "Finalize live stream - stop time " + edgeMeta.recording_stop_time,
1078
+ publish: false // Don't publish this version because it is not currently useful
1079
+ });
1080
+ case 57:
1081
+ fin = _context6.sent;
1082
+ return _context6.abrupt("return", {
1083
+ fin: fin,
1084
+ name: name,
1085
+ edge_write_token: edgeWriteToken,
1086
+ state: "terminated"
1087
+ });
1088
+ case 61:
1089
+ _context6.prev = 61;
1090
+ _context6.t1 = _context6["catch"](1);
1091
+ console.error(_context6.t1);
1092
+ case 64:
1093
+ case "end":
1094
+ return _context6.stop();
1095
+ }
1096
+ }, _callee6, this, [[1, 61], [27, 32]]);
1097
+ }));
1098
+ return function (_x6) {
1099
+ return _ref12.apply(this, arguments);
1100
+ };
1101
+ }();
1102
+
1103
+ /**
1104
+ * Initialize the stream object
1105
+ *
1106
+ * @methodGroup Live Stream
1107
+ * @namedParams
1108
+ * @param {string} name - Object ID or name of the live stream object
1109
+ * @param {boolean=} drm - If specified, playout will be DRM protected
1110
+ * @param {string=} format - Specify the list of playout formats and DRM to support,
1111
+ comma-separated (hls-clear, hls-aes128, hls-sample-aes,
1112
+ hls-fairplay)
1113
+ *
1114
+ * @return {Promise<Object>} - The name, object ID, and state of the stream
1115
+ */
1116
+ exports.StreamInitialize = /*#__PURE__*/function () {
1117
+ var _ref14 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee7(_ref13) {
1118
+ var name, _ref13$drm, drm, format, contentTypes, typeAbrMaster, typeLiveStream, i, key, res;
1119
+ return _regeneratorRuntime.wrap(function _callee7$(_context7) {
1120
+ while (1) switch (_context7.prev = _context7.next) {
1121
+ case 0:
1122
+ name = _ref13.name, _ref13$drm = _ref13.drm, drm = _ref13$drm === void 0 ? false : _ref13$drm, format = _ref13.format;
1123
+ _context7.next = 3;
1124
+ return this.ContentTypes();
1125
+ case 3:
1126
+ contentTypes = _context7.sent;
1127
+ for (i = 0; i < Object.keys(contentTypes).length; i++) {
1128
+ key = Object.keys(contentTypes)[i];
1129
+ if (contentTypes[key].name.includes("ABR Master") || contentTypes[key].name.includes("Title")) {
1130
+ typeAbrMaster = contentTypes[key].hash;
1131
+ }
1132
+ if (contentTypes[key].name.includes("Live Stream")) {
1133
+ typeLiveStream = contentTypes[key].hash;
1134
+ }
1135
+ }
1136
+ if (!(typeAbrMaster === undefined || typeLiveStream === undefined)) {
1137
+ _context7.next = 8;
1138
+ break;
1139
+ }
1140
+ console.log("ERROR - unable to find content types", "ABR Master", typeAbrMaster, "Live Stream", typeLiveStream);
1141
+ return _context7.abrupt("return", {});
1142
+ case 8:
1143
+ _context7.next = 10;
1144
+ return this.StreamSetOfferingAndDRM({
1145
+ name: name,
1146
+ typeAbrMaster: typeAbrMaster,
1147
+ typeLiveStream: typeLiveStream,
1148
+ drm: drm,
1149
+ format: format
1150
+ });
1151
+ case 10:
1152
+ res = _context7.sent;
1153
+ return _context7.abrupt("return", res);
1154
+ case 12:
1155
+ case "end":
1156
+ return _context7.stop();
1157
+ }
1158
+ }, _callee7, this);
1159
+ }));
1160
+ return function (_x7) {
1161
+ return _ref14.apply(this, arguments);
1162
+ };
1163
+ }();
1164
+
1165
+ /**
1166
+ * Set the Live Stream offering
1167
+ *
1168
+ * @methodGroup Live Stream
1169
+ * @namedParams
1170
+ * @param {string} name - Object ID or name of the live stream object
1171
+ * @param {string=} typeAbrMaster - Content type hash
1172
+ * @param {string=} typeLiveStream - Content type hash
1173
+ * @param {boolean=} drm - If specified, DRM will be applied to the stream
1174
+ * @param {string=} format - A list of playout formats and DRM to support, comma-separated
1175
+ * (hls-clear, hls-aes128, hls-sample-aes, hls-fairplay). If specified,
1176
+ * this will take precedence over the drm value
1177
+ *
1178
+ * @return {Promise<Object>} - The name, object ID, and state of the stream
1179
+ */
1180
+ exports.StreamSetOfferingAndDRM = /*#__PURE__*/function () {
1181
+ var _ref16 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee8(_ref15) {
1182
+ var name, typeAbrMaster, typeLiveStream, _ref15$drm, drm, format, status, objectId, aBitRate, aChannels, aSampleRate, aStreamIndex, aTimeBase, aChannelLayout, vBitRate, vHeight, vStreamIndex, vWidth, vDisplayAspectRatio, vFrameRate, vTimeBase, abrProfile, playoutFormats, formats, i, libraryId, mainMeta, fabURI, streamUrl;
1183
+ return _regeneratorRuntime.wrap(function _callee8$(_context8) {
1184
+ while (1) switch (_context8.prev = _context8.next) {
1185
+ case 0:
1186
+ name = _ref15.name, typeAbrMaster = _ref15.typeAbrMaster, typeLiveStream = _ref15.typeLiveStream, _ref15$drm = _ref15.drm, drm = _ref15$drm === void 0 ? false : _ref15$drm, format = _ref15.format;
1187
+ _context8.next = 3;
1188
+ return this.StreamStatus({
1189
+ name: name
1190
+ });
1191
+ case 3:
1192
+ status = _context8.sent;
1193
+ if (!(status.state != "inactive" && status.state != "stopped")) {
1194
+ _context8.next = 6;
1195
+ break;
1196
+ }
1197
+ return _context8.abrupt("return", {
1198
+ state: status.state,
1199
+ error: "stream still active - must terminate first"
1200
+ });
1201
+ case 6:
1202
+ objectId = status.object_id;
1203
+ console.log("INIT: ", name, objectId);
1204
+ aBitRate = 128000;
1205
+ aChannels = 2;
1206
+ aSampleRate = 48000;
1207
+ aStreamIndex = 1;
1208
+ aTimeBase = "1/48000";
1209
+ aChannelLayout = "stereo";
1210
+ vBitRate = 14000000;
1211
+ vHeight = 720;
1212
+ vStreamIndex = 0;
1213
+ vWidth = 1280;
1214
+ vDisplayAspectRatio = "16/9";
1215
+ vFrameRate = "30000/1001";
1216
+ vTimeBase = "1/30000"; // "1/16000";
1217
+ abrProfile = require("../abr_profiles/abr_profile_live_drm.js");
1218
+ playoutFormats = abrProfile.playout_formats;
1219
+ if (!format) {
1220
+ _context8.next = 39;
1221
+ break;
1222
+ }
1223
+ drm = true; // Override DRM parameter
1224
+ playoutFormats = {};
1225
+ formats = format.split(",");
1226
+ i = 0;
1227
+ case 28:
1228
+ if (!(i < formats.length)) {
1229
+ _context8.next = 37;
1230
+ break;
1231
+ }
1232
+ if (!(formats[i] === "hls-clear")) {
1233
+ _context8.next = 33;
1234
+ break;
1235
+ }
1236
+ abrProfile.drm_optional = true;
1237
+ playoutFormats["hls-clear"] = {
1238
+ "drm": null,
1239
+ "protocol": {
1240
+ "type": "ProtoHls"
1241
+ }
1242
+ };
1243
+ return _context8.abrupt("continue", 34);
1244
+ case 33:
1245
+ playoutFormats[formats[i]] = abrProfile.playout_formats[formats[i]];
1246
+ case 34:
1247
+ i++;
1248
+ _context8.next = 28;
1249
+ break;
1250
+ case 37:
1251
+ _context8.next = 40;
1252
+ break;
1253
+ case 39:
1254
+ if (!drm) {
1255
+ abrProfile.drm_optional = true;
1256
+ playoutFormats = {
1257
+ "hls-clear": {
1258
+ "drm": null,
1259
+ "protocol": {
1260
+ "type": "ProtoHls"
1261
+ }
1262
+ }
1263
+ };
1264
+ }
1265
+ case 40:
1266
+ abrProfile.playout_formats = playoutFormats;
1267
+ _context8.next = 43;
1268
+ return this.ContentObjectLibraryId({
1269
+ objectId: objectId
1270
+ });
1271
+ case 43:
1272
+ libraryId = _context8.sent;
1273
+ _context8.prev = 44;
1274
+ _context8.next = 47;
1275
+ return this.ContentObjectMetadata({
1276
+ libraryId: libraryId,
1277
+ objectId: objectId
1278
+ });
1279
+ case 47:
1280
+ mainMeta = _context8.sent;
1281
+ fabURI = mainMeta.live_recording.fabric_config.ingress_node_api; // Support both hostname and URL ingress_node_api
1282
+ if (!fabURI.startsWith("http")) {
1283
+ // Assume https
1284
+ fabURI = "https://" + fabURI;
1285
+ }
1286
+ this.SetNodes({
1287
+ fabricURIs: [fabURI]
1288
+ });
1289
+ streamUrl = mainMeta.live_recording.recording_config.recording_params.origin_url;
1290
+ _context8.next = 54;
1291
+ return StreamGenerateOffering({
1292
+ client: this,
1293
+ libraryId: libraryId,
1294
+ objectId: objectId,
1295
+ typeAbrMaster: typeAbrMaster,
1296
+ typeLiveStream: typeLiveStream,
1297
+ streamUrl: streamUrl,
1298
+ abrProfile: abrProfile,
1299
+ aBitRate: aBitRate,
1300
+ aChannels: aChannels,
1301
+ aSampleRate: aSampleRate,
1302
+ aStreamIndex: aStreamIndex,
1303
+ aTimeBase: aTimeBase,
1304
+ aChannelLayout: aChannelLayout,
1305
+ vBitRate: vBitRate,
1306
+ vHeight: vHeight,
1307
+ vStreamIndex: vStreamIndex,
1308
+ vWidth: vWidth,
1309
+ vDisplayAspectRatio: vDisplayAspectRatio,
1310
+ vFrameRate: vFrameRate,
1311
+ vTimeBase: vTimeBase
1312
+ });
1313
+ case 54:
1314
+ console.log("Finished generating offering");
1315
+ return _context8.abrupt("return", {
1316
+ name: name,
1317
+ object_id: objectId,
1318
+ state: "initialized"
1319
+ });
1320
+ case 58:
1321
+ _context8.prev = 58;
1322
+ _context8.t0 = _context8["catch"](44);
1323
+ console.error(_context8.t0);
1324
+ case 61:
1325
+ case "end":
1326
+ return _context8.stop();
1327
+ }
1328
+ }, _callee8, this, [[44, 58]]);
1329
+ }));
1330
+ return function (_x8) {
1331
+ return _ref16.apply(this, arguments);
1332
+ };
1333
+ }();
1334
+
1335
+ /**
1336
+ * Add a content insertion entry
1337
+ *
1338
+ * @methodGroup Live Stream
1339
+ * @namedParams
1340
+ * @param {string} name - Object ID or name of the live stream object
1341
+ * @param {number} insertionTime - Time in seconds (float)
1342
+ * @param {boolean=} sinceStart - If specified, time specified will be elapsed seconds
1343
+ * since stream start, otherwise, time will be elapsed since epoch
1344
+ * @param {number=} duration - Time in seconds (float). Default: 20.0
1345
+ * @param {string} targetHash - The target content object hash (playable)
1346
+ * @param {boolean=} remove - If specified, will remove the inseration at the exact 'time' (instead of adding)
1347
+ *
1348
+ * @return {Promise<Object>} - Insertions, as well as any errors from bad insertions
1349
+ */
1350
+ exports.StreamInsertion = /*#__PURE__*/function () {
1351
+ var _ref18 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee9(_ref17) {
1352
+ var name, insertionTime, _ref17$sinceStart, sinceStart, duration, targetHash, _ref17$remove, remove, offeringMeta, insertionInfo, audioAbrDuration, videoAbrDuration, conf, libraryId, objectId, mainMeta, fabURI, edgeWriteToken, edgeMeta, recordings, sequence, streamStartTime, period, playoutConfig, insertions, res, errs, currentTime, insertionDone, newInsertion, i;
1353
+ return _regeneratorRuntime.wrap(function _callee9$(_context9) {
1354
+ while (1) switch (_context9.prev = _context9.next) {
1355
+ case 0:
1356
+ name = _ref17.name, insertionTime = _ref17.insertionTime, _ref17$sinceStart = _ref17.sinceStart, sinceStart = _ref17$sinceStart === void 0 ? false : _ref17$sinceStart, duration = _ref17.duration, targetHash = _ref17.targetHash, _ref17$remove = _ref17.remove, remove = _ref17$remove === void 0 ? false : _ref17$remove;
1357
+ _context9.next = 3;
1358
+ return this.ContentObjectMetadata({
1359
+ versionHash: targetHash,
1360
+ metadataSubtree: "/offerings/default"
1361
+ });
1362
+ case 3:
1363
+ offeringMeta = _context9.sent;
1364
+ insertionInfo = {
1365
+ duration_sec: 0 // Minimum of video and audio duration
1366
+ };
1367
+
1368
+ ["video", "audio"].forEach(function (mt) {
1369
+ var stream = offeringMeta.media_struct.streams[mt];
1370
+ insertionInfo[mt] = {
1371
+ seg_duration_sec: stream.optimum_seg_dur["float"],
1372
+ duration_sec: stream.duration["float"],
1373
+ frame_rate_rat: stream.rate
1374
+ };
1375
+ if (insertionInfo.duration_sec === 0 || stream.duration["float"] < insertionInfo.duration_sec) {
1376
+ insertionInfo.duration_sec = stream.duration["float"];
1377
+ }
1378
+ });
1379
+ audioAbrDuration = insertionInfo.audio.seg_duration_sec;
1380
+ videoAbrDuration = insertionInfo.video.seg_duration_sec;
1381
+ if (!(audioAbrDuration === 0 || videoAbrDuration === 0)) {
1382
+ _context9.next = 10;
1383
+ break;
1384
+ }
1385
+ throw new Error("Bad segment duration hash:", targetHash);
1386
+ case 10:
1387
+ if (!(duration === undefined)) {
1388
+ _context9.next = 14;
1389
+ break;
1390
+ }
1391
+ duration = insertionInfo.duration_sec; // Use full duration of the insertion
1392
+ _context9.next = 16;
1393
+ break;
1394
+ case 14:
1395
+ if (!(duration > insertionInfo.duration_sec)) {
1396
+ _context9.next = 16;
1397
+ break;
1398
+ }
1399
+ throw new Error("Bad duration - larger than insertion object duration", insertionInfo.duration_sec);
1400
+ case 16:
1401
+ _context9.next = 18;
1402
+ return this.LoadConf({
1403
+ name: name
1404
+ });
1405
+ case 18:
1406
+ conf = _context9.sent;
1407
+ _context9.next = 21;
1408
+ return this.ContentObjectLibraryId({
1409
+ objectId: conf.objectId
1410
+ });
1411
+ case 21:
1412
+ libraryId = _context9.sent;
1413
+ objectId = conf.objectId;
1414
+ _context9.next = 25;
1415
+ return this.ContentObjectMetadata({
1416
+ libraryId: libraryId,
1417
+ objectId: conf.objectId
1418
+ });
1419
+ case 25:
1420
+ mainMeta = _context9.sent;
1421
+ fabURI = mainMeta.live_recording.fabric_config.ingress_node_api; // Support both hostname and URL ingress_node_api
1422
+ if (!fabURI.startsWith("http")) {
1423
+ // Assume https
1424
+ fabURI = "https://" + fabURI;
1425
+ }
1426
+ this.SetNodes({
1427
+ fabricURIs: [fabURI]
1428
+ });
1429
+ edgeWriteToken = mainMeta.live_recording.fabric_config.edge_write_token;
1430
+ _context9.next = 32;
1431
+ return this.ContentObjectMetadata({
1432
+ libraryId: libraryId,
1433
+ objectId: conf.objectId,
1434
+ writeToken: edgeWriteToken
1435
+ });
1436
+ case 32:
1437
+ edgeMeta = _context9.sent;
1438
+ // Find stream start time (from the most recent recording section)
1439
+ recordings = edgeMeta.live_recording.recordings;
1440
+ sequence = 1;
1441
+ streamStartTime = 0;
1442
+ if (recordings != undefined && recordings.recording_sequence != undefined) {
1443
+ // We have at least one recording - check if still active
1444
+ sequence = recordings.recording_sequence;
1445
+ period = recordings.live_offering[sequence - 1];
1446
+ if (period.end_time_epoch_sec > 0) {
1447
+ // The last period is closed - apply insertions to the next period
1448
+ sequence++;
1449
+ } else {
1450
+ // The period is active
1451
+ streamStartTime = period.start_time_epoch_sec;
1452
+ }
1453
+ }
1454
+ if (!(streamStartTime === 0)) {
1455
+ _context9.next = 40;
1456
+ break;
1457
+ }
1458
+ if (!(sinceStart === false)) {
1459
+ _context9.next = 40;
1460
+ break;
1461
+ }
1462
+ throw new Error("Stream not running - must use 'time since start'");
1463
+ case 40:
1464
+ // Find the current period playout configuration
1465
+ if (edgeMeta.live_recording.playout_config.interleaves === undefined) {
1466
+ edgeMeta.live_recording.playout_config.interleaves = {};
1467
+ }
1468
+ if (edgeMeta.live_recording.playout_config.interleaves[sequence] === undefined) {
1469
+ edgeMeta.live_recording.playout_config.interleaves[sequence] = [];
1470
+ }
1471
+ playoutConfig = edgeMeta.live_recording.playout_config;
1472
+ insertions = playoutConfig.interleaves[sequence];
1473
+ res = {};
1474
+ if (!sinceStart) {
1475
+ insertionTime = insertionTime - streamStartTime;
1476
+ }
1477
+
1478
+ // Assume insertions are sorted by insertion time
1479
+ errs = [];
1480
+ currentTime = -1;
1481
+ insertionDone = false;
1482
+ newInsertion = {
1483
+ insertion_time: insertionTime,
1484
+ duration: duration,
1485
+ audio_abr_duration: audioAbrDuration,
1486
+ video_abr_duration: videoAbrDuration,
1487
+ playout: "/qfab/" + targetHash + "/rep/playout" // TO FIX - should be a link
1488
+ };
1489
+ i = 0;
1490
+ case 51:
1491
+ if (!(i < insertions.length)) {
1492
+ _context9.next = 66;
1493
+ break;
1494
+ }
1495
+ if (insertions[i].insertion_time <= currentTime) {
1496
+ // Bad insertion - must be later than current time
1497
+ append(errs, "Bad insertion - time:", insertions[i].insertion_time);
1498
+ }
1499
+ if (!remove) {
1500
+ _context9.next = 59;
1501
+ break;
1502
+ }
1503
+ if (!(insertions[i].insertion_time === insertionTime)) {
1504
+ _context9.next = 57;
1505
+ break;
1506
+ }
1507
+ insertions.splice(i, 1);
1508
+ return _context9.abrupt("break", 66);
1509
+ case 57:
1510
+ _context9.next = 63;
1511
+ break;
1512
+ case 59:
1513
+ if (!(insertions[i].insertion_time > insertionTime)) {
1514
+ _context9.next = 63;
1515
+ break;
1516
+ }
1517
+ if (i > 0) {
1518
+ insertions = [].concat(_toConsumableArray(insertions.splice(0, i)), [newInsertion], _toConsumableArray(insertions.splice(i)));
1519
+ } else {
1520
+ insertions = [newInsertion].concat(_toConsumableArray(insertions.splice(i)));
1521
+ }
1522
+ insertionDone = true;
1523
+ return _context9.abrupt("break", 66);
1524
+ case 63:
1525
+ i++;
1526
+ _context9.next = 51;
1527
+ break;
1528
+ case 66:
1529
+ if (!remove && !insertionDone) {
1530
+ // Add to the end of the insertions list
1531
+ console.log("Add insertion at the end");
1532
+ insertions = [].concat(_toConsumableArray(insertions), [newInsertion]);
1533
+ }
1534
+ playoutConfig.interleaves[sequence] = insertions;
1535
+
1536
+ // Store the new insertions in the write token
1537
+ _context9.next = 70;
1538
+ return this.ReplaceMetadata({
1539
+ libraryId: libraryId,
1540
+ objectId: objectId,
1541
+ writeToken: edgeWriteToken,
1542
+ metadataSubtree: "/live_recording/playout_config",
1543
+ metadata: edgeMeta.live_recording.playout_config
1544
+ });
1545
+ case 70:
1546
+ res.errors = errs;
1547
+ res.insertions = insertions;
1548
+ return _context9.abrupt("return", res);
1549
+ case 73:
1550
+ case "end":
1551
+ return _context9.stop();
1552
+ }
1553
+ }, _callee9, this);
1554
+ }));
1555
+ return function (_x9) {
1556
+ return _ref18.apply(this, arguments);
1557
+ };
1558
+ }();
1559
+
1560
+ /**
1561
+ * Load cached stream configuration
1562
+ *
1563
+ * @methodGroup Live Stream
1564
+ * @namedParams
1565
+ * @param {string} name - Object ID or name of the live stream object
1566
+ *
1567
+ * @return {Promise<Object>} - The configuration of the stream
1568
+ */
1569
+ exports.LoadConf = /*#__PURE__*/function () {
1570
+ var _ref20 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee10(_ref19) {
1571
+ var name, streamsBuf, streams, conf;
1572
+ return _regeneratorRuntime.wrap(function _callee10$(_context10) {
1573
+ while (1) switch (_context10.prev = _context10.next) {
1574
+ case 0:
1575
+ name = _ref19.name;
1576
+ if (!name.startsWith("iq__")) {
1577
+ _context10.next = 3;
1578
+ break;
1579
+ }
1580
+ return _context10.abrupt("return", {
1581
+ name: name,
1582
+ objectId: name
1583
+ });
1584
+ case 3:
1585
+ _context10.prev = 3;
1586
+ streamsBuf = fs.readFileSync(path.resolve(__dirname, "../liveconf.json"));
1587
+ _context10.next = 11;
1588
+ break;
1589
+ case 7:
1590
+ _context10.prev = 7;
1591
+ _context10.t0 = _context10["catch"](3);
1592
+ console.log("Stream name must be a QID or a label in liveconf.json");
1593
+ return _context10.abrupt("return", {});
1594
+ case 11:
1595
+ streams = JSON.parse(streamsBuf);
1596
+ conf = streams[name];
1597
+ if (!(conf === null)) {
1598
+ _context10.next = 16;
1599
+ break;
1600
+ }
1601
+ console.log("Bad name: ", name);
1602
+ return _context10.abrupt("return", {});
1603
+ case 16:
1604
+ return _context10.abrupt("return", conf);
1605
+ case 17:
1606
+ case "end":
1607
+ return _context10.stop();
1608
+ }
1609
+ }, _callee10, null, [[3, 7]]);
1610
+ }));
1611
+ return function (_x10) {
1612
+ return _ref20.apply(this, arguments);
1613
+ };
1614
+ }();
1615
+
1616
+ /**
1617
+ * Configure the stream
1618
+ *
1619
+ * @methodGroup Live Stream
1620
+ * @namedParams
1621
+ * @param {string} name - Object ID or name of the live stream object
1622
+ * @param {Object=} customSettings - Additional options to customize configuration settings
1623
+ * - audioBitrate
1624
+ * - audioIndex
1625
+ * - partTtl
1626
+ * - channelLayout
1627
+ *
1628
+ * @return {Promise<Object>} - The status response for the stream
1629
+ *
1630
+ */
1631
+ exports.StreamConfig = /*#__PURE__*/function () {
1632
+ var _ref22 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee11(_ref21) {
1633
+ var name, _ref21$customSettings, customSettings, conf, status, libraryId, mainMeta, userConfig, hostName, streamUrl, nodes, node, endpoint, probe, controller, timeoutId, probeUrl, lc, liveRecordingConfigStr, liveRecordingConfig, e, writeToken;
1634
+ return _regeneratorRuntime.wrap(function _callee11$(_context11) {
1635
+ while (1) switch (_context11.prev = _context11.next) {
1636
+ case 0:
1637
+ name = _ref21.name, _ref21$customSettings = _ref21.customSettings, customSettings = _ref21$customSettings === void 0 ? {} : _ref21$customSettings;
1638
+ _context11.next = 3;
1639
+ return this.LoadConf({
1640
+ name: name
1641
+ });
1642
+ case 3:
1643
+ conf = _context11.sent;
1644
+ status = {
1645
+ name: name
1646
+ };
1647
+ _context11.next = 7;
1648
+ return this.ContentObjectLibraryId({
1649
+ objectId: conf.objectId
1650
+ });
1651
+ case 7:
1652
+ libraryId = _context11.sent;
1653
+ status.library_id = libraryId;
1654
+ status.object_id = conf.objectId;
1655
+ _context11.next = 12;
1656
+ return this.ContentObjectMetadata({
1657
+ libraryId: libraryId,
1658
+ objectId: conf.objectId
1659
+ });
1660
+ case 12:
1661
+ mainMeta = _context11.sent;
1662
+ userConfig = mainMeta.live_recording_config;
1663
+ status.user_config = userConfig;
1664
+ console.log("userConfig", userConfig);
1665
+
1666
+ // Get node URI from user config
1667
+ hostName = userConfig.url.replace("udp://", "").replace("rtmp://", "").replace("srt://", "").split(":")[0];
1668
+ streamUrl = new URL(userConfig.url);
1669
+ console.log("Retrieving nodes...");
1670
+ _context11.next = 21;
1671
+ return this.SpaceNodes({
1672
+ matchEndpoint: hostName
1673
+ });
1674
+ case 21:
1675
+ nodes = _context11.sent;
1676
+ if (!(nodes.length < 1)) {
1677
+ _context11.next = 25;
1678
+ break;
1679
+ }
1680
+ status.error = "No node matching stream URL " + streamUrl.href;
1681
+ return _context11.abrupt("return", status);
1682
+ case 25:
1362
1683
  node = nodes[0];
1363
1684
  status.node = node;
1364
1685
  endpoint = node.endpoints[0];
@@ -1372,17 +1693,17 @@ exports.StreamConfig = /*#__PURE__*/function () {
1372
1693
  timeoutId = setTimeout(function () {
1373
1694
  controller.abort();
1374
1695
  }, 60 * 1000); // milliseconds
1375
- _context6.prev = 31;
1376
- _context6.next = 34;
1696
+ _context11.prev = 32;
1697
+ _context11.next = 35;
1377
1698
  return this.Rep({
1378
1699
  libraryId: libraryId,
1379
1700
  objectId: conf.objectId,
1380
1701
  rep: "probe"
1381
1702
  });
1382
- case 34:
1383
- probeUrl = _context6.sent;
1384
- _context6.t0 = this.utils;
1385
- _context6.next = 38;
1703
+ case 35:
1704
+ probeUrl = _context11.sent;
1705
+ _context11.t0 = this.utils;
1706
+ _context11.next = 39;
1386
1707
  return HttpClient.Fetch(probeUrl, {
1387
1708
  body: JSON.stringify({
1388
1709
  "filename": streamUrl.href,
@@ -1391,35 +1712,34 @@ exports.StreamConfig = /*#__PURE__*/function () {
1391
1712
  method: "POST",
1392
1713
  signal: controller.signal
1393
1714
  });
1394
- case 38:
1395
- _context6.t1 = _context6.sent;
1396
- _context6.next = 41;
1397
- return _context6.t0.ResponseToJson.call(_context6.t0, _context6.t1);
1398
- case 41:
1399
- probe = _context6.sent;
1715
+ case 39:
1716
+ _context11.t1 = _context11.sent;
1717
+ _context11.next = 42;
1718
+ return _context11.t0.ResponseToJson.call(_context11.t0, _context11.t1);
1719
+ case 42:
1720
+ probe = _context11.sent;
1400
1721
  if (probe) {
1401
1722
  clearTimeout(timeoutId);
1402
1723
  }
1403
1724
  if (!probe.errors) {
1404
- _context6.next = 45;
1725
+ _context11.next = 46;
1405
1726
  break;
1406
1727
  }
1407
1728
  throw probe.errors[0];
1408
- case 45:
1409
- _context6.next = 54;
1729
+ case 46:
1730
+ _context11.next = 55;
1410
1731
  break;
1411
- case 47:
1412
- _context6.prev = 47;
1413
- _context6.t2 = _context6["catch"](31);
1414
- if (!(_context6.t2.code === "ETIMEDOUT")) {
1415
- _context6.next = 53;
1732
+ case 48:
1733
+ _context11.prev = 48;
1734
+ _context11.t2 = _context11["catch"](32);
1735
+ if (!(_context11.t2.code === "ETIMEDOUT")) {
1736
+ _context11.next = 54;
1416
1737
  break;
1417
1738
  }
1418
1739
  throw "Stream probe time out - make sure the stream source is available";
1419
- case 53:
1420
- throw _context6.t2;
1421
1740
  case 54:
1422
- console.log("PROBE", probe);
1741
+ throw _context11.t2;
1742
+ case 55:
1423
1743
  probe.format.filename = streamUrl.href;
1424
1744
 
1425
1745
  // Create live recording config
@@ -1434,15 +1754,15 @@ exports.StreamConfig = /*#__PURE__*/function () {
1434
1754
  console.log("CONFIG", JSON.stringify(liveRecordingConfig.live_recording));
1435
1755
 
1436
1756
  // Store live recording config into the stream object
1437
- _context6.next = 62;
1757
+ _context11.next = 62;
1438
1758
  return this.EditContentObject({
1439
1759
  libraryId: libraryId,
1440
1760
  objectId: conf.objectId
1441
1761
  });
1442
1762
  case 62:
1443
- e = _context6.sent;
1763
+ e = _context11.sent;
1444
1764
  writeToken = e.write_token;
1445
- _context6.next = 66;
1765
+ _context11.next = 66;
1446
1766
  return this.ReplaceMetadata({
1447
1767
  libraryId: libraryId,
1448
1768
  objectId: conf.objectId,
@@ -1451,349 +1771,157 @@ exports.StreamConfig = /*#__PURE__*/function () {
1451
1771
  metadata: liveRecordingConfig.live_recording
1452
1772
  });
1453
1773
  case 66:
1454
- _context6.next = 68;
1455
- return this.ReplaceMetadata({
1456
- libraryId: libraryId,
1457
- objectId: conf.objectId,
1458
- writeToken: writeToken,
1459
- metadataSubtree: "probe",
1460
- metadata: probe
1461
- });
1462
- case 68:
1463
- _context6.next = 70;
1774
+ _context11.next = 68;
1464
1775
  return this.FinalizeContentObject({
1465
1776
  libraryId: libraryId,
1466
1777
  objectId: conf.objectId,
1467
1778
  writeToken: writeToken,
1468
1779
  commitMessage: "Apply live stream configuration"
1469
1780
  });
1781
+ case 68:
1782
+ status.fin = _context11.sent;
1783
+ return _context11.abrupt("return", status);
1470
1784
  case 70:
1471
- status.fin = _context6.sent;
1472
- return _context6.abrupt("return", status);
1473
- case 72:
1474
1785
  case "end":
1475
- return _context6.stop();
1786
+ return _context11.stop();
1476
1787
  }
1477
- }, _callee6, this, [[31, 47]]);
1788
+ }, _callee11, this, [[32, 48]]);
1478
1789
  }));
1479
- return function (_x6) {
1480
- return _ref12.apply(this, arguments);
1790
+ return function (_x11) {
1791
+ return _ref22.apply(this, arguments);
1481
1792
  };
1482
1793
  }();
1483
1794
 
1484
- // const ChannelStatus = async ({client, name}) => {
1485
- //
1486
- // let status = {name: name};
1487
- //
1488
- // const conf = channels[name];
1489
- // if(conf === null) {
1490
- // console.log("Bad name: ", name);
1491
- // return;
1492
- // }
1493
- //
1494
- // try {
1495
- //
1496
- // let meta = await client.ContentObjectMetadata({
1497
- // libraryId: conf.libraryId,
1498
- // objectId: conf.objectId
1499
- // });
1500
- //
1501
- // status.channel_title = meta.public.asset_metadata.title;
1502
- // let source = meta.channel.offerings.default.items[0].source["/"];
1503
- // let hash = source.split("/")[2];
1504
- // status.stream_hash = hash;
1505
- // latestHash = await client.LatestVersionHash({
1506
- // versionHash: hash
1507
- // });
1508
- // status.stream_latest_hash = latestHash;
1509
- //
1510
- // if(hash != latestHash) {
1511
- // status.warnings = ["Stream version is not the latest"];
1512
- // }
1513
- //
1514
- // let channelFormatsUrl = await client.FabricUrl({
1515
- // libraryId: conf.libraryId,
1516
- // objectId: conf.objectId,
1517
- // rep: "channel/options.json"
1518
- // });
1519
- //
1520
- // try {
1521
- // let offerings = await got(channelFormatsUrl);
1522
- // status.offerings = JSON.parse(offerings.body);
1523
- // } catch(error) {
1524
- // console.log(error);
1525
- // status.offerings_error = "Failed to retrieve channel offerings";
1526
- // }
1527
- //
1528
- // status.playout = await ChannelPlayout({client, libraryId: conf.libraryId, objectId: conf.objectId});
1529
- //
1530
- // } catch(error) {
1531
- // console.error(error);
1532
- // }
1533
- //
1534
- // return status;
1535
- // };
1536
-
1537
- /*
1538
- * Performs client-side playout operations - open the channel, read offerings,
1539
- * retrieve playlist and one video init segment.
1540
- */
1541
- // const ChannelPlayout = async({client, libraryId, objectId}) => {
1542
- //
1543
- // let playout = {};
1544
- //
1545
- // const offerings = await client.AvailableOfferings({
1546
- // libraryId,
1547
- // objectId,
1548
- // handler: "channel",
1549
- // linkPath: "/public/asset_metadata/offerings"
1550
- // });
1551
- //
1552
- // // Choosing offering 'default'
1553
- // let offering = offerings.default;
1554
- //
1555
- // const playoutOptions = await client.PlayoutOptions({
1556
- // libraryId,
1557
- // objectId,
1558
- // offeringURI: offering.uri
1559
- // });
1560
- //
1561
- // // Retrieve master playlist
1562
- // let masterPlaylistUrl = playoutOptions["hls"]["playoutMethods"]["fairplay"]["playoutUrl"];
1563
- // playout.master_playlist_url = masterPlaylistUrl;
1564
- // try {
1565
- // //let masterPlaylist = await got(masterPlaylistUrl);
1566
- // playout.master_playlist = "success";
1567
- // } catch(error) {
1568
- // playout.master_playlist = "fail";
1569
- // }
1570
- //
1571
- // let url = new URL(masterPlaylistUrl);
1572
- // let p = url.pathname.split("/");
1573
- //
1574
- // // Retrieve media playlist
1575
- // p[p.length - 1] = "video/720@14000000/live.m3u8";
1576
- // let pathMediaPlaylist = p.join("/");
1577
- // url.pathname = pathMediaPlaylist;
1578
- // let mediaPlaylistUrl = url.toString();
1579
- // playout.media_playlist_url = mediaPlaylistUrl;
1580
- // let mediaPlaylist;
1581
- // try {
1582
- // mediaPlaylist = await got(mediaPlaylistUrl);
1583
- // playout.media_playlist = "success";
1584
- // } catch(error) {
1585
- // playout.media_playlist = "fail";
1586
- // }
1587
- //
1588
- // // Retrieve init segment
1589
- // var regex = new RegExp("^#EXT-X-MAP:URI=\"init.m4s.(.*)\"$", "m");
1590
- // var match = regex.exec(mediaPlaylist.body);
1591
- // let initQueryParams;
1592
- // if(match) {
1593
- // initQueryParams = match[1];
1594
- // }
1595
- //
1596
- // p[p.length - 1] = "video/720@14000000/init.m4s";
1597
- // let pathInit = p.join("/");
1598
- // url.pathname = pathInit;
1599
- // url.search=initQueryParams;
1600
- // let initUrl = url.toString();
1601
- // playout.init_segment_url = initUrl;
1602
- // /*
1603
- // try {
1604
- // let initSegment = await got(initUrl);
1605
- // playout.init_segment = "success"
1606
- // } catch(error) {
1607
- // playout.init_segment = "fail";
1608
- // }
1609
- // */
1610
- // return playout;
1611
- // };
1612
-
1613
- // const Summary = async ({client}) => {
1614
- //
1615
- // let summary = {};
1616
- //
1617
- // try {
1618
- // for (const [key] of Object.entries(streams)) {
1619
- // conf = streams[key];
1620
- // summary[key] = await Status({client, name: key, stopLro: false});
1621
- // }
1622
- //
1623
- // } catch(error) {
1624
- // console.error(error);
1625
- // }
1626
- // return summary;
1627
- // };
1628
-
1629
- // const ChannelSummary = async ({client}) => {
1630
- //
1631
- // let summary = {};
1632
- //
1633
- // try {
1634
- // for (const [key] of Object.entries(channels)) {
1635
- // conf = channels[key];
1636
- // summary[key] = await ChannelStatus({client, name: key});
1637
- // }
1638
- //
1639
- // } catch(error) {
1640
- // console.error(error);
1641
- // }
1642
- // return summary;
1643
- // };
1644
-
1645
- // const ConfigStreamRebroadcast = async () => {
1646
- //
1647
- // const t = 1619850660;
1648
- //
1649
- // try {
1650
- // let client;
1651
- // if(conf.clientConf.configUrl) {
1652
- // client = await ElvClient.FromConfigurationUrl({
1653
- // configUrl: conf.clientConf.configUrl
1654
- // });
1655
- // } else {
1656
- // client = new ElvClient(conf.clientConf);
1657
- // }
1658
- // const wallet = client.GenerateWallet();
1659
- // const signer = wallet.AddAccount({ privateKey: conf.signerPrivateKey });
1660
- // client.SetSigner({ signer });
1661
- // const fabURI = client.fabricURIs[0];
1662
- // console.log("Fabric URI: " + fabURI);
1663
- // const ethURI = client.ethereumURIs[0];
1664
- // console.log("Ethereum URI: " + ethURI);
1665
- //
1666
- // client.ToggleLogging(false);
1667
- //
1668
- // let mainMeta = await client.ContentObjectMetadata({
1669
- // libraryId: conf.libraryId,
1670
- // objectId: conf.objectId
1671
- // });
1672
- // console.log("Main meta:", mainMeta);
1673
- //
1674
- // edgeWriteToken = mainMeta.edge_write_token;
1675
- // console.log("Edge: ", edgeWriteToken);
1676
- //
1677
- // let edgeMeta = await client.ContentObjectMetadata({
1678
- // libraryId: conf.libraryId,
1679
- // objectId: conf.objectId,
1680
- // writeToken: edgeWriteToken
1681
- // });
1682
- // console.log("Edge meta:", edgeMeta);
1683
- //
1684
- // //console.log("CONFIG: ", edgeMeta.live_recording_parameters.live_playout_config);
1685
- // console.log("recording_start_time: ", edgeMeta.recording_start_time);
1686
- // console.log("recording_stop_time: ", edgeMeta.recording_stop_time);
1687
- //
1688
- // // Set rebroadcast start
1689
- // edgeMeta.live_recording_parameters.live_playout_config.rebroadcast_start_time_sec_epoch = t;
1690
- //
1691
- // if(PRINT_DEBUG) console.log("MergeMetadata", conf.libraryId, conf.objectId, writeToken);
1692
- // await client.MergeMetadata({
1693
- // libraryId: conf.libraryId,
1694
- // objectId: conf.objectId,
1695
- // writeToken: edgeWriteToken,
1696
- // metadata: {
1697
- // "live_recording_parameters": {
1698
- // "live_playout_config" : edgeMeta.live_recording_parameters.live_playout_config
1699
- // }
1700
- // }
1701
- // });
1702
- //
1703
- // } catch(error) {
1704
- // console.error(error);
1705
- // }
1706
- // };
1707
-
1708
- // async function EnsureAll() {
1709
- // client = await StatusPrep({name: null});
1710
- // let summary = await Summary({client});
1711
- //
1712
- // var res = {
1713
- // running: 0,
1714
- // stalled: 0,
1715
- // terminated: 0
1716
- // };
1717
- //
1718
- // try {
1719
- // for (const [key, value] of Object.entries(summary)) {
1720
- // if(value.state === "stalled") {
1721
- // console.log("Stream stalled: ", key, " - restarting");
1722
- // console.log("todo ...");
1723
- // }
1724
- // res[value.state] = res[value.state] + 1;
1725
- // }
1726
- // } catch(error) {
1727
- // console.error(error);
1728
- // }
1729
- //
1730
- // return res;
1731
- // }
1732
-
1733
- /*
1734
- * Original Run() function - kept for reference
1795
+ /**
1796
+ * Deactivate the stream
1797
+ *
1798
+ * @methodGroup Live Stream
1799
+ * @namedParams
1800
+ * @param {string} name - Object ID or name of the live stream object
1801
+ *
1802
+ * @return {Promise<Object>} - The status response for the stream
1735
1803
  */
1736
- // async function Run() {
1737
- //
1738
- // var client;
1739
- //
1740
- // switch (command) {
1741
- //
1742
- // case "start":
1743
- // StartStream({name});
1744
- // break;
1745
- //
1746
- // case "status":
1747
- // client = await StatusPrep({name});
1748
- // let status = await Status({client, name, stopLro: false});
1749
- // console.log(JSON.stringify(status, null, 4));
1750
- // break;
1751
- //
1752
- // case "stop":
1753
- // client = await UpdatePrep({name});
1754
- // Status({client, name, stopLro: true});
1755
- // break;
1756
- //
1757
- // case "summary":
1758
- // client = await StatusPrep({name: null});
1759
- // let summary = await Summary({client});
1760
- // console.log(JSON.stringify(summary, null, 4));
1761
- // break;
1762
- //
1763
- // case "init": // Set up DRM
1764
- // SetOfferingAndDRM();
1765
- // break;
1766
- //
1767
- // case "reset": // Stop and start LRO recording (same edge write token)
1768
- // client = await StatusPrep({name});
1769
- // let reset = await Reset({client, name, stopLro: false});
1770
- // console.log(JSON.stringify(reset, null, 4));
1771
- // break;
1772
- //
1773
- // case "channel":
1774
- // client = await StatusPrep({name});
1775
- // let channelStatus = await ChannelStatus({client, name});
1776
- // console.log(JSON.stringify(channelStatus, null, 4));
1777
- // break;
1778
- //
1779
- // case "channel_summary":
1780
- // client = await StatusPrep({name});
1781
- // let channelSummary = await ChannelSummary({client, name});
1782
- // console.log(JSON.stringify(channelSummary, null, 4));
1783
- // break;
1784
- //
1785
- // case "ensure_all": // Check all and restart stalled
1786
- // let ensureSummary = await EnsureAll();
1787
- // console.log(JSON.stringify(ensureSummary, null, 4));
1788
- // break;
1789
- //
1790
- // case "future_use_config":
1791
- // ConfigStreamRebroadcast();
1792
- // break;
1793
- //
1794
- // default:
1795
- // console.log("Bad command: ", command);
1796
- // break;
1797
- //
1798
- // }
1799
- // }
1804
+ exports.StreamDeactivate = /*#__PURE__*/function () {
1805
+ var _ref24 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee12(_ref23) {
1806
+ var name, conf, objectId, libraryId, mainMeta, status, fabURI, edgeWriteToken, edgeMeta, newState, fin;
1807
+ return _regeneratorRuntime.wrap(function _callee12$(_context12) {
1808
+ while (1) switch (_context12.prev = _context12.next) {
1809
+ case 0:
1810
+ name = _ref23.name;
1811
+ _context12.prev = 1;
1812
+ _context12.next = 4;
1813
+ return this.LoadConf({
1814
+ name: name
1815
+ });
1816
+ case 4:
1817
+ conf = _context12.sent;
1818
+ objectId = conf.objectId;
1819
+ _context12.next = 8;
1820
+ return this.ContentObjectLibraryId({
1821
+ objectId: objectId
1822
+ });
1823
+ case 8:
1824
+ libraryId = _context12.sent;
1825
+ _context12.next = 11;
1826
+ return this.ContentObjectMetadata({
1827
+ libraryId: libraryId,
1828
+ objectId: objectId
1829
+ });
1830
+ case 11:
1831
+ mainMeta = _context12.sent;
1832
+ _context12.next = 14;
1833
+ return this.StreamStatus({
1834
+ name: name
1835
+ });
1836
+ case 14:
1837
+ status = _context12.sent;
1838
+ if (mainMeta.live_recording) {
1839
+ _context12.next = 17;
1840
+ break;
1841
+ }
1842
+ return _context12.abrupt("return", {
1843
+ state: status.state,
1844
+ error: "Stream must be configured before deactivating"
1845
+ });
1846
+ case 17:
1847
+ if (!(status.state !== "stopped")) {
1848
+ _context12.next = 19;
1849
+ break;
1850
+ }
1851
+ return _context12.abrupt("return", {
1852
+ state: status.state,
1853
+ error: "Stream must be stopped before deactivating"
1854
+ });
1855
+ case 19:
1856
+ fabURI = mainMeta.live_recording.fabric_config.ingress_node_api; // Support both hostname and URL ingress_node_api
1857
+ if (!fabURI.startsWith("http")) {
1858
+ // Assume https
1859
+ fabURI = "https://" + fabURI;
1860
+ }
1861
+ this.SetNodes({
1862
+ fabricURIs: [fabURI]
1863
+ });
1864
+ edgeWriteToken = mainMeta.live_recording.fabric_config.edge_write_token;
1865
+ if (!(edgeWriteToken === undefined || edgeWriteToken === "")) {
1866
+ _context12.next = 25;
1867
+ break;
1868
+ }
1869
+ return _context12.abrupt("return", {
1870
+ state: "inactive",
1871
+ error: "stream is already inactive"
1872
+ });
1873
+ case 25:
1874
+ _context12.next = 27;
1875
+ return this.ContentObjectMetadata({
1876
+ libraryId: libraryId,
1877
+ objectId: objectId,
1878
+ writeToken: edgeWriteToken
1879
+ });
1880
+ case 27:
1881
+ edgeMeta = _context12.sent;
1882
+ // Set stop time
1883
+ edgeMeta.recording_stop_time = Math.floor(new Date().getTime() / 1000);
1884
+ newState = "inactive";
1885
+ edgeMeta.live_recording.status = {
1886
+ state: newState,
1887
+ recording_stop_time: edgeMeta.recording_stop_time
1888
+ };
1889
+ edgeMeta.live_recording.fabric_config.edge_write_token = "";
1890
+ _context12.next = 34;
1891
+ return this.ReplaceMetadata({
1892
+ libraryId: libraryId,
1893
+ objectId: objectId,
1894
+ writeToken: edgeWriteToken,
1895
+ metadata: edgeMeta
1896
+ });
1897
+ case 34:
1898
+ _context12.next = 36;
1899
+ return this.FinalizeContentObject({
1900
+ libraryId: libraryId,
1901
+ objectId: objectId,
1902
+ writeToken: edgeWriteToken,
1903
+ commitMessage: "Deactivate stream"
1904
+ });
1905
+ case 36:
1906
+ fin = _context12.sent;
1907
+ return _context12.abrupt("return", {
1908
+ reference_url: status.reference_url,
1909
+ fin: fin,
1910
+ name: name,
1911
+ edge_write_token: edgeWriteToken,
1912
+ state: newState
1913
+ });
1914
+ case 40:
1915
+ _context12.prev = 40;
1916
+ _context12.t0 = _context12["catch"](1);
1917
+ console.error(_context12.t0);
1918
+ case 43:
1919
+ case "end":
1920
+ return _context12.stop();
1921
+ }
1922
+ }, _callee12, this, [[1, 40]]);
1923
+ }));
1924
+ return function (_x12) {
1925
+ return _ref24.apply(this, arguments);
1926
+ };
1927
+ }();