@eluvio/elv-client-js 4.0.76 → 4.0.77

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 (35) 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 +2 -2
  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 +1 -1
  23. package/dist/src/client/LiveStream.js +1157 -1153
  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 +3 -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/LiveConf.js +1 -1
  35. package/src/client/LiveStream.js +809 -936
@@ -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,63 +337,63 @@ 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;
108
375
  if (!(mainMeta.live_recording_config == undefined || mainMeta.live_recording_config.url == undefined)) {
109
- _context2.next = 17;
376
+ _context3.next = 17;
110
377
  break;
111
378
  }
112
379
  status.state = "unconfigured";
113
- return _context2.abrupt("return", status);
380
+ return _context3.abrupt("return", status);
114
381
  case 17:
115
382
  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;
383
+ _context3.next = 20;
117
384
  break;
118
385
  }
119
386
  status.state = "uninitialized";
120
- return _context2.abrupt("return", status);
387
+ return _context3.abrupt("return", status);
121
388
  case 20:
122
389
  fabURI = mainMeta.live_recording.fabric_config.ingress_node_api;
123
390
  if (!(fabURI === undefined)) {
124
- _context2.next = 25;
391
+ _context3.next = 25;
125
392
  break;
126
393
  }
127
394
  console.log("bad fabric config - missing ingress node API");
128
395
  status.state = "uninitialized";
129
- return _context2.abrupt("return", status);
396
+ return _context3.abrupt("return", status);
130
397
  case 25:
131
398
  // Support both hostname and URL ingress_node_api
132
399
  if (!fabURI.startsWith("http")) {
@@ -137,11 +404,11 @@ exports.StreamStatus = /*#__PURE__*/function () {
137
404
  status.url = mainMeta.live_recording.recording_config.recording_params.origin_url;
138
405
  edgeWriteToken = mainMeta.live_recording.fabric_config.edge_write_token;
139
406
  if (!(edgeWriteToken == undefined)) {
140
- _context2.next = 32;
407
+ _context3.next = 32;
141
408
  break;
142
409
  }
143
410
  status.state = "inactive";
144
- return _context2.abrupt("return", status);
411
+ return _context3.abrupt("return", status);
145
412
  case 32:
146
413
  this.RecordWriteToken({
147
414
  writeToken: edgeWriteToken,
@@ -149,7 +416,7 @@ exports.StreamStatus = /*#__PURE__*/function () {
149
416
  });
150
417
  status.edge_write_token = edgeWriteToken;
151
418
  status.stream_id = edgeWriteToken; // By convention the stream ID is its write token
152
- _context2.next = 37;
419
+ _context3.next = 37;
153
420
  return this.ContentObjectMetadata({
154
421
  libraryId: libraryId,
155
422
  objectId: conf.objectId,
@@ -157,14 +424,17 @@ exports.StreamStatus = /*#__PURE__*/function () {
157
424
  select: ["live_recording"]
158
425
  });
159
426
  case 37:
160
- edgeMeta = _context2.sent;
427
+ edgeMeta = _context3.sent;
428
+ status.edge_meta_size = JSON.stringify(edgeMeta).length;
429
+
430
+ // If a stream has never been started return state 'inactive'
161
431
  if (!(edgeMeta.live_recording === undefined || edgeMeta.live_recording.recordings === undefined || edgeMeta.live_recording.recordings.recording_sequence === undefined)) {
162
- _context2.next = 41;
432
+ _context3.next = 42;
163
433
  break;
164
434
  }
165
435
  status.state = "stopped";
166
- return _context2.abrupt("return", status);
167
- case 41:
436
+ return _context3.abrupt("return", status);
437
+ case 42:
168
438
  recordings = edgeMeta.live_recording.recordings;
169
439
  status.recording_period_sequence = recordings.recording_sequence;
170
440
  sequence = recordings.recording_sequence;
@@ -183,15 +453,15 @@ exports.StreamStatus = /*#__PURE__*/function () {
183
453
  video_since_last_finalize_sec: sinceLastFinalize
184
454
  };
185
455
  status.recording_period = recording_period;
186
- _context2.next = 52;
456
+ _context3.next = 53;
187
457
  return this.FabricUrl({
188
458
  libraryId: libraryId,
189
459
  objectId: conf.objectId,
190
460
  writeToken: edgeWriteToken,
191
461
  call: "live/status/" + tlro
192
462
  });
193
- case 52:
194
- status.lro_status_url = _context2.sent;
463
+ case 53:
464
+ status.lro_status_url = _context3.sent;
195
465
  status.insertions = [];
196
466
  if (edgeMeta.live_recording.playout_config.interleaves != undefined && edgeMeta.live_recording.playout_config.interleaves[sequence] != undefined) {
197
467
  insertions = edgeMeta.live_recording.playout_config.interleaves[sequence];
@@ -206,31 +476,31 @@ exports.StreamStatus = /*#__PURE__*/function () {
206
476
  }
207
477
  }
208
478
  if (showParams) {
209
- status.recording_paramse = edgeMeta.live_recording.recording_config.recording_params;
479
+ status.recording_params = edgeMeta.live_recording.recording_config.recording_params;
210
480
  }
211
481
  state = "stopped";
212
482
  lroStatus = "";
213
- _context2.prev = 58;
214
- _context2.t0 = this.utils;
215
- _context2.next = 62;
483
+ _context3.prev = 59;
484
+ _context3.t0 = this.utils;
485
+ _context3.next = 63;
216
486
  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;
487
+ case 63:
488
+ _context3.t1 = _context3.sent;
489
+ _context3.next = 66;
490
+ return _context3.t0.ResponseToJson.call(_context3.t0, _context3.t1);
491
+ case 66:
492
+ lroStatus = _context3.sent;
223
493
  state = lroStatus.state;
224
- _context2.next = 75;
494
+ _context3.next = 76;
225
495
  break;
226
- case 69:
227
- _context2.prev = 69;
228
- _context2.t2 = _context2["catch"](58);
229
- console.log("LRO Status (failed): ", _context2.t2.response.statusCode);
496
+ case 70:
497
+ _context3.prev = 70;
498
+ _context3.t2 = _context3["catch"](59);
499
+ console.log("LRO Status (failed): ", _context3.t2.response.statusCode);
230
500
  status.state = "stopped";
231
- status.error = _context2.t2.response;
232
- return _context2.abrupt("return", status);
233
- case 75:
501
+ status.error = _context3.t2.response;
502
+ return _context3.abrupt("return", status);
503
+ case 76:
234
504
  // Convert LRO 'state' to desired 'state'
235
505
  if (state === "running" && period.video_finalized_parts_info.last_finalization_time === 0) {
236
506
  state = "starting";
@@ -241,98 +511,98 @@ exports.StreamStatus = /*#__PURE__*/function () {
241
511
  }
242
512
  status.state = state;
243
513
  if (!((state === "running" || state === "stalled" || state === "starting") && stopLro)) {
244
- _context2.next = 96;
514
+ _context3.next = 97;
245
515
  break;
246
516
  }
247
- _context2.next = 80;
517
+ _context3.next = 81;
248
518
  return this.FabricUrl({
249
519
  libraryId: libraryId,
250
520
  objectId: conf.objectId,
251
521
  writeToken: edgeWriteToken,
252
522
  call: "live/stop/" + tlro
253
523
  });
254
- case 80:
255
- lroStopUrl = _context2.sent;
256
- _context2.prev = 81;
257
- _context2.t3 = this.utils;
258
- _context2.next = 85;
524
+ case 81:
525
+ lroStopUrl = _context3.sent;
526
+ _context3.prev = 82;
527
+ _context3.t3 = this.utils;
528
+ _context3.next = 86;
259
529
  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:
530
+ case 86:
531
+ _context3.t4 = _context3.sent;
532
+ _context3.next = 89;
533
+ return _context3.t3.ResponseToJson.call(_context3.t3, _context3.t4);
534
+ case 89:
265
535
  console.log("LRO Stop: ", lroStatus.body);
266
- _context2.next = 94;
536
+ _context3.next = 95;
267
537
  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:
538
+ case 92:
539
+ _context3.prev = 92;
540
+ _context3.t5 = _context3["catch"](82);
541
+ console.log("LRO Stop (failed): ", _context3.t5.response.statusCode);
542
+ case 95:
273
543
  state = "stopped";
274
544
  status.state = state;
275
- case 96:
545
+ case 97:
276
546
  if (!(state === "running")) {
277
- _context2.next = 128;
547
+ _context3.next = 129;
278
548
  break;
279
549
  }
280
550
  playout_urls = {};
281
551
  objectId = conf.objectId;
282
- _context2.next = 101;
552
+ _context3.next = 102;
283
553
  return this.PlayoutOptions({
284
554
  objectId: objectId,
285
555
  linkPath: "public/asset_metadata/sources/default"
286
556
  });
287
- case 101:
288
- playout_options = _context2.sent;
557
+ case 102:
558
+ playout_options = _context3.sent;
289
559
  hls_clear_enabled = playout_options && playout_options.hls && playout_options.hls.playoutMethods && playout_options.hls.playoutMethods.clear !== undefined;
290
560
  if (!hls_clear_enabled) {
291
- _context2.next = 107;
561
+ _context3.next = 108;
292
562
  break;
293
563
  }
294
- _context2.next = 106;
564
+ _context3.next = 107;
295
565
  return this.FabricUrl({
296
566
  libraryId: libraryId,
297
567
  objectId: objectId,
298
568
  rep: "playout/default/hls-clear/playlist.m3u8"
299
569
  });
300
- case 106:
301
- playout_urls.hls_clear = _context2.sent;
302
570
  case 107:
571
+ playout_urls.hls_clear = _context3.sent;
572
+ case 108:
303
573
  hls_aes128_enabled = playout_options && playout_options.hls && playout_options.hls.playoutMethods && playout_options.hls.playoutMethods["aes-128"] !== undefined;
304
574
  if (!hls_aes128_enabled) {
305
- _context2.next = 112;
575
+ _context3.next = 113;
306
576
  break;
307
577
  }
308
- _context2.next = 111;
578
+ _context3.next = 112;
309
579
  return this.FabricUrl({
310
580
  libraryId: libraryId,
311
581
  objectId: objectId,
312
582
  rep: "playout/default/hls-aes128/playlist.m3u8"
313
583
  });
314
- case 111:
315
- playout_urls.hls_aes128 = _context2.sent;
316
584
  case 112:
585
+ playout_urls.hls_aes128 = _context3.sent;
586
+ case 113:
317
587
  hls_sample_aes_enabled = playout_options && playout_options.hls && playout_options.hls.playoutMethods && playout_options.hls.playoutMethods["sample-aes"] !== undefined;
318
588
  if (!hls_sample_aes_enabled) {
319
- _context2.next = 117;
589
+ _context3.next = 118;
320
590
  break;
321
591
  }
322
- _context2.next = 116;
592
+ _context3.next = 117;
323
593
  return this.FabricUrl({
324
594
  libraryId: libraryId,
325
595
  objectId: objectId,
326
596
  rep: "playout/default/hls-sample-aes/playlist.m3u8"
327
597
  });
328
- case 116:
329
- playout_urls.hls_sample_aes = _context2.sent;
330
598
  case 117:
331
- _context2.next = 119;
599
+ playout_urls.hls_sample_aes = _context3.sent;
600
+ case 118:
601
+ _context3.next = 120;
332
602
  return this.NetworkInfo();
333
- case 119:
334
- networkInfo = _context2.sent;
335
- _context2.next = 122;
603
+ case 120:
604
+ networkInfo = _context3.sent;
605
+ _context3.next = 123;
336
606
  return this.authClient.AuthorizationToken({
337
607
  libraryId: libraryId,
338
608
  objectId: objectId,
@@ -340,8 +610,8 @@ exports.StreamStatus = /*#__PURE__*/function () {
340
610
  noCache: true,
341
611
  noAuth: true
342
612
  });
343
- case 122:
344
- token = _context2.sent;
613
+ case 123:
614
+ token = _context3.sent;
345
615
  embed_net = "main";
346
616
  if (networkInfo.name.includes("demo")) {
347
617
  embed_net = "demo";
@@ -349,92 +619,75 @@ exports.StreamStatus = /*#__PURE__*/function () {
349
619
  embed_url = "https://embed.v3.contentfabric.io/?net=".concat(embed_net, "&p&ct=h&oid=").concat(conf.objectId, "&mt=lv&ath=").concat(token);
350
620
  playout_urls.embed_url = embed_url;
351
621
  status.playout_urls = playout_urls;
352
- case 128:
353
- _context2.next = 133;
622
+ case 129:
623
+ _context3.next = 134;
354
624
  break;
355
- 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);
625
+ case 131:
626
+ _context3.prev = 131;
627
+ _context3.t6 = _context3["catch"](5);
628
+ console.error(_context3.t6);
361
629
  case 134:
630
+ return _context3.abrupt("return", status);
631
+ case 135:
362
632
  case "end":
363
- return _context2.stop();
633
+ return _context3.stop();
364
634
  }
365
- }, _callee2, this, [[5, 130], [58, 69], [81, 91]]);
635
+ }, _callee3, this, [[5, 131], [59, 70], [82, 92]]);
366
636
  }));
367
- return function (_x2) {
368
- return _ref4.apply(this, arguments);
637
+ return function (_x3) {
638
+ return _ref6.apply(this, arguments);
369
639
  };
370
640
  }();
371
641
 
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
642
  /**
390
643
  * Create a new edge write token
391
644
  *
392
645
  * @methodGroup Live Stream
393
646
  * @namedParams
394
- * @param {string} name -
395
- * @param {boolean} start -
647
+ * @param {string} name - Object ID or name of the live stream object
648
+ * @param {boolean=} start - If specified, will start the stream after creation
396
649
  *
397
- * @return {Object} - The status response for the object
650
+ * @return {Promise<Object>} - The status response for the object
398
651
  *
399
652
  */
400
653
  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) {
654
+ var _ref8 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee4(_ref7) {
655
+ var name, _ref7$start, start, status, objectId, libraryId, liveRecording, fabURI, response, edgeToken, writeToken, objectHash;
656
+ return _regeneratorRuntime.wrap(function _callee4$(_context4) {
657
+ while (1) switch (_context4.prev = _context4.next) {
405
658
  case 0:
406
- name = _ref5.name, _ref5$start = _ref5.start, start = _ref5$start === void 0 ? false : _ref5$start;
407
- _context3.next = 3;
659
+ name = _ref7.name, _ref7$start = _ref7.start, start = _ref7$start === void 0 ? false : _ref7$start;
660
+ _context4.next = 3;
408
661
  return this.StreamStatus({
409
662
  name: name
410
663
  });
411
664
  case 3:
412
- status = _context3.sent;
665
+ status = _context4.sent;
413
666
  if (!(status.state !== "inactive" && status.state !== "terminated" && status.state !== "stopped")) {
414
- _context3.next = 6;
667
+ _context4.next = 6;
415
668
  break;
416
669
  }
417
- return _context3.abrupt("return", {
670
+ return _context4.abrupt("return", {
418
671
  state: status.state,
419
672
  error: "stream still active - must terminate first"
420
673
  });
421
674
  case 6:
422
675
  objectId = status.object_id;
423
676
  console.log("START: ", name, "start", start);
424
- _context3.next = 10;
677
+ _context4.next = 10;
425
678
  return this.ContentObjectLibraryId({
426
679
  objectId: objectId
427
680
  });
428
681
  case 10:
429
- libraryId = _context3.sent;
430
- _context3.next = 13;
682
+ libraryId = _context4.sent;
683
+ _context4.next = 13;
431
684
  return this.ContentObjectMetadata({
432
685
  libraryId: libraryId,
433
686
  objectId: objectId,
434
687
  metadataSubtree: "/live_recording"
435
688
  });
436
689
  case 13:
437
- liveRecording = _context3.sent;
690
+ liveRecording = _context4.sent;
438
691
  fabURI = liveRecording.fabric_config.ingress_node_api; // Support both hostname and URL ingress_node_api
439
692
  if (!fabURI.startsWith("http")) {
440
693
  // Assume https
@@ -444,29 +697,29 @@ exports.StreamCreate = /*#__PURE__*/function () {
444
697
  fabricURIs: [fabURI]
445
698
  });
446
699
  console.log("Node URI", fabURI, "ID", liveRecording.fabric_config.ingress_node_id);
447
- _context3.next = 20;
700
+ _context4.next = 20;
448
701
  return this.EditContentObject({
449
702
  libraryId: libraryId,
450
703
  objectId: objectId
451
704
  });
452
705
  case 20:
453
- response = _context3.sent;
706
+ response = _context4.sent;
454
707
  edgeToken = response.write_token;
455
708
  console.log("Edge token:", edgeToken);
456
709
 
457
710
  /*
458
711
  * Set the metadata, including the edge token.
459
712
  */
460
- _context3.next = 25;
713
+ _context4.next = 25;
461
714
  return this.EditContentObject({
462
715
  libraryId: libraryId,
463
716
  objectId: objectId
464
717
  });
465
718
  case 25:
466
- response = _context3.sent;
719
+ response = _context4.sent;
467
720
  writeToken = response.write_token;
468
721
  this.Log("Merging metadata: ", libraryId, objectId, writeToken);
469
- _context3.next = 30;
722
+ _context4.next = 30;
470
723
  return this.MergeMetadata({
471
724
  libraryId: libraryId,
472
725
  objectId: objectId,
@@ -486,7 +739,7 @@ exports.StreamCreate = /*#__PURE__*/function () {
486
739
  });
487
740
  case 30:
488
741
  this.Log("Finalizing content draft: ", libraryId, objectId, writeToken);
489
- _context3.next = 33;
742
+ _context4.next = 33;
490
743
  return this.FinalizeContentObject({
491
744
  libraryId: libraryId,
492
745
  objectId: objectId,
@@ -494,7 +747,7 @@ exports.StreamCreate = /*#__PURE__*/function () {
494
747
  commitMessage: "Create stream edge write token " + edgeToken
495
748
  });
496
749
  case 33:
497
- response = _context3.sent;
750
+ response = _context4.sent;
498
751
  objectHash = response.hash;
499
752
  this.Log("Finalized object: ", objectHash);
500
753
  status = {
@@ -512,15 +765,15 @@ exports.StreamCreate = /*#__PURE__*/function () {
512
765
  op: start
513
766
  });
514
767
  }
515
- return _context3.abrupt("return", status);
768
+ return _context4.abrupt("return", status);
516
769
  case 39:
517
770
  case "end":
518
- return _context3.stop();
771
+ return _context4.stop();
519
772
  }
520
- }, _callee3, this);
773
+ }, _callee4, this);
521
774
  }));
522
- return function (_x3) {
523
- return _ref6.apply(this, arguments);
775
+ return function (_x4) {
776
+ return _ref8.apply(this, arguments);
524
777
  };
525
778
  }();
526
779
 
@@ -529,50 +782,50 @@ exports.StreamCreate = /*#__PURE__*/function () {
529
782
  *
530
783
  * @methodGroup Live Stream
531
784
  * @namedParams
532
- * @param {string} name -
533
- * @param {string=} op - The operation to perform. Possible values:
785
+ * @param {string} name - Object ID or name of the live stream object
786
+ * @param {string} op - The operation to perform. Possible values:
534
787
  * 'start'
535
788
  * 'reset' - Stops current LRO recording and starts a new one. Does
536
789
  * not create a new edge write token (just creates a new recording
537
790
  * period in the existing edge write token)
538
791
  * - 'stop'
539
792
  *
540
- * @return {Object} - The status response for the stream
793
+ * @return {Promise<Object>} - The status response for the stream
541
794
  *
542
795
  */
543
796
  exports.StreamStartOrStopOrReset = /*#__PURE__*/function () {
544
- var _ref8 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee4(_ref7) {
797
+ var _ref10 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee5(_ref9) {
545
798
  var name, op, status, _tries, tries;
546
- return _regeneratorRuntime.wrap(function _callee4$(_context4) {
547
- while (1) switch (_context4.prev = _context4.next) {
799
+ return _regeneratorRuntime.wrap(function _callee5$(_context5) {
800
+ while (1) switch (_context5.prev = _context5.next) {
548
801
  case 0:
549
- name = _ref7.name, op = _ref7.op;
550
- _context4.prev = 1;
802
+ name = _ref9.name, op = _ref9.op;
803
+ _context5.prev = 1;
551
804
  console.log("Stream ", op, ": ", name);
552
- _context4.next = 5;
805
+ _context5.next = 5;
553
806
  return this.StreamStatus({
554
807
  name: name
555
808
  });
556
809
  case 5:
557
- status = _context4.sent;
810
+ status = _context5.sent;
558
811
  if (!(status.state != "stopped")) {
559
- _context4.next = 10;
812
+ _context5.next = 10;
560
813
  break;
561
814
  }
562
815
  if (!(op === "start")) {
563
- _context4.next = 10;
816
+ _context5.next = 10;
564
817
  break;
565
818
  }
566
819
  status.error = "Unable to start stream - state: " + status.state;
567
- return _context4.abrupt("return", status);
820
+ return _context5.abrupt("return", status);
568
821
  case 10:
569
822
  if (!(status.state == "running" || status.state == "starting" || status.state == "stalled")) {
570
- _context4.next = 33;
823
+ _context5.next = 33;
571
824
  break;
572
825
  }
573
826
  console.log("STOPPING");
574
- _context4.prev = 12;
575
- _context4.next = 15;
827
+ _context5.prev = 12;
828
+ _context5.next = 15;
576
829
  return this.CallBitcodeMethod({
577
830
  libraryId: status.library_id,
578
831
  objectId: status.object_id,
@@ -581,49 +834,49 @@ exports.StreamStartOrStopOrReset = /*#__PURE__*/function () {
581
834
  constant: false
582
835
  });
583
836
  case 15:
584
- _context4.next = 19;
837
+ _context5.next = 19;
585
838
  break;
586
839
  case 17:
587
- _context4.prev = 17;
588
- _context4.t0 = _context4["catch"](12);
840
+ _context5.prev = 17;
841
+ _context5.t0 = _context5["catch"](12);
589
842
  case 19:
590
843
  // Wait until LRO is terminated
591
844
  _tries = 10;
592
845
  case 20:
593
846
  if (!(status.state != "stopped" && _tries-- > 0)) {
594
- _context4.next = 29;
847
+ _context5.next = 29;
595
848
  break;
596
849
  }
597
850
  console.log("Wait to terminate - ", status.state);
598
- _context4.next = 24;
599
- return sleep(1000);
851
+ _context5.next = 24;
852
+ return Sleep(1000);
600
853
  case 24:
601
- _context4.next = 26;
854
+ _context5.next = 26;
602
855
  return this.StreamStatus({
603
856
  name: name
604
857
  });
605
858
  case 26:
606
- status = _context4.sent;
607
- _context4.next = 20;
859
+ status = _context5.sent;
860
+ _context5.next = 20;
608
861
  break;
609
862
  case 29:
610
- console.log("Status after terminate - ", status.state);
863
+ console.log("Status after stop - ", status.state);
611
864
  if (!(_tries <= 0)) {
612
- _context4.next = 33;
865
+ _context5.next = 33;
613
866
  break;
614
867
  }
615
- console.log("Failed to terminate");
616
- return _context4.abrupt("return", status);
868
+ console.log("Failed to stop");
869
+ return _context5.abrupt("return", status);
617
870
  case 33:
618
871
  if (!(op === "stop")) {
619
- _context4.next = 35;
872
+ _context5.next = 35;
620
873
  break;
621
874
  }
622
- return _context4.abrupt("return", status);
875
+ return _context5.abrupt("return", status);
623
876
  case 35:
624
877
  console.log("STARTING", "edge_write_token", status.edge_write_token);
625
- _context4.prev = 36;
626
- _context4.next = 39;
878
+ _context5.prev = 36;
879
+ _context5.next = 39;
627
880
  return this.CallBitcodeMethod({
628
881
  libraryId: status.library_id,
629
882
  objectId: status.object_id,
@@ -632,13 +885,13 @@ exports.StreamStartOrStopOrReset = /*#__PURE__*/function () {
632
885
  constant: false
633
886
  });
634
887
  case 39:
635
- _context4.next = 45;
888
+ _context5.next = 45;
636
889
  break;
637
890
  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", {
891
+ _context5.prev = 41;
892
+ _context5.t1 = _context5["catch"](36);
893
+ console.log("LRO Start (failed): ", _context5.t1);
894
+ return _context5.abrupt("return", {
642
895
  state: status.state,
643
896
  error: "LRO start failed - must create a stream first"
644
897
  });
@@ -647,698 +900,766 @@ exports.StreamStartOrStopOrReset = /*#__PURE__*/function () {
647
900
  tries = 10;
648
901
  case 46:
649
902
  if (!(status.state != "starting" && tries-- > 0)) {
650
- _context4.next = 55;
903
+ _context5.next = 55;
651
904
  break;
652
905
  }
653
906
  console.log("Wait to start - ", status.state);
654
- _context4.next = 50;
655
- return sleep(1000);
907
+ _context5.next = 50;
908
+ return Sleep(1000);
656
909
  case 50:
657
- _context4.next = 52;
910
+ _context5.next = 52;
658
911
  return this.StreamStatus({
659
912
  name: name
660
913
  });
661
914
  case 52:
662
- status = _context4.sent;
663
- _context4.next = 46;
915
+ status = _context5.sent;
916
+ _context5.next = 46;
664
917
  break;
665
918
  case 55:
666
919
  console.log("Status after restart - ", status.state);
667
- return _context4.abrupt("return", status);
920
+ return _context5.abrupt("return", status);
668
921
  case 59:
669
- _context4.prev = 59;
670
- _context4.t2 = _context4["catch"](1);
671
- console.error(_context4.t2);
922
+ _context5.prev = 59;
923
+ _context5.t2 = _context5["catch"](1);
924
+ console.error(_context5.t2);
672
925
  case 62:
673
926
  case "end":
674
- return _context4.stop();
927
+ return _context5.stop();
675
928
  }
676
- }, _callee4, this, [[1, 59], [12, 17], [36, 41]]);
929
+ }, _callee5, this, [[1, 59], [12, 17], [36, 41]]);
677
930
  }));
678
- return function (_x4) {
679
- return _ref8.apply(this, arguments);
931
+ return function (_x5) {
932
+ return _ref10.apply(this, arguments);
680
933
  };
681
934
  }();
682
935
 
683
- /*
936
+ /**
684
937
  * Stop the live stream session and close the edge write token.
685
938
  * Not implemented fully
939
+ *
940
+ * @methodGroup Live Stream
941
+ * @namedParams
942
+ * @param {string} name - Object ID or name of the live stream object
943
+ *
944
+ * @return {Promise<Object>} - The finalize response for the stream object
686
945
  */
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
- // }
946
+ exports.StreamStopSession = /*#__PURE__*/function () {
947
+ var _ref12 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee6(_ref11) {
948
+ var name, conf, objectId, libraryId, mainMeta, fabURI, edgeWriteToken, edgeMeta, status, tries, fin;
949
+ return _regeneratorRuntime.wrap(function _callee6$(_context6) {
950
+ while (1) switch (_context6.prev = _context6.next) {
951
+ case 0:
952
+ name = _ref11.name;
953
+ _context6.prev = 1;
954
+ console.log("TERMINATE: ", name);
955
+ _context6.next = 5;
956
+ return this.LoadConf({
957
+ name: name
958
+ });
959
+ case 5:
960
+ conf = _context6.sent;
961
+ objectId = conf.objectId;
962
+ _context6.next = 9;
963
+ return this.ContentObjectLibraryId({
964
+ objectId: objectId
965
+ });
966
+ case 9:
967
+ libraryId = _context6.sent;
968
+ _context6.next = 12;
969
+ return this.ContentObjectMetadata({
970
+ libraryId: libraryId,
971
+ objectId: objectId
972
+ });
973
+ case 12:
974
+ mainMeta = _context6.sent;
975
+ fabURI = mainMeta.live_recording.fabric_config.ingress_node_api; // Support both hostname and URL ingress_node_api
976
+ if (!fabURI.startsWith("http")) {
977
+ // Assume https
978
+ fabURI = "https://" + fabURI;
979
+ }
980
+ this.SetNodes({
981
+ fabricURIs: [fabURI]
982
+ });
983
+ edgeWriteToken = mainMeta.live_recording.fabric_config.edge_write_token;
984
+ if (!(edgeWriteToken === undefined || edgeWriteToken === "")) {
985
+ _context6.next = 19;
986
+ break;
987
+ }
988
+ return _context6.abrupt("return", {
989
+ state: "inactive",
990
+ error: "no active streams - must create a stream first"
991
+ });
992
+ case 19:
993
+ _context6.next = 21;
994
+ return this.ContentObjectMetadata({
995
+ libraryId: libraryId,
996
+ objectId: objectId,
997
+ writeToken: edgeWriteToken
998
+ });
999
+ case 21:
1000
+ edgeMeta = _context6.sent;
1001
+ _context6.next = 24;
1002
+ return this.StreamStatus({
1003
+ name: name
1004
+ });
1005
+ case 24:
1006
+ status = _context6.sent;
1007
+ if (!(status.state != "terminated")) {
1008
+ _context6.next = 48;
1009
+ break;
1010
+ }
1011
+ console.log("STOPPING");
1012
+ _context6.prev = 27;
1013
+ _context6.next = 30;
1014
+ return this.CallBitcodeMethod({
1015
+ libraryId: status.library_id,
1016
+ objectId: status.object_id,
1017
+ writeToken: status.edge_write_token,
1018
+ method: "/live/stop/" + status.tlro,
1019
+ constant: false
1020
+ });
1021
+ case 30:
1022
+ _context6.next = 34;
1023
+ break;
1024
+ case 32:
1025
+ _context6.prev = 32;
1026
+ _context6.t0 = _context6["catch"](27);
1027
+ case 34:
1028
+ // Wait until LRO is terminated
1029
+ tries = 10;
1030
+ case 35:
1031
+ if (!(status.state != "stopped" && tries-- > 0)) {
1032
+ _context6.next = 44;
1033
+ break;
1034
+ }
1035
+ console.log("Wait to terminate - ", status.state);
1036
+ _context6.next = 39;
1037
+ return Sleep(1000);
1038
+ case 39:
1039
+ _context6.next = 41;
1040
+ return this.StreamStatus({
1041
+ name: name
1042
+ });
1043
+ case 41:
1044
+ status = _context6.sent;
1045
+ _context6.next = 35;
1046
+ break;
1047
+ case 44:
1048
+ console.log("Status after stop - ", status.state);
1049
+ if (!(tries <= 0)) {
1050
+ _context6.next = 48;
1051
+ break;
1052
+ }
1053
+ console.log("Failed to stop");
1054
+ return _context6.abrupt("return", status);
1055
+ case 48:
1056
+ // Set stop time
1057
+ edgeMeta.recording_stop_time = Math.floor(new Date().getTime() / 1000);
1058
+ console.log("recording_start_time: ", edgeMeta.recording_start_time);
1059
+ console.log("recording_stop_time: ", edgeMeta.recording_stop_time);
1060
+ edgeMeta.live_recording.status = {
1061
+ state: "terminated",
1062
+ recording_stop_time: edgeMeta.recording_stop_time
1063
+ };
1064
+ edgeMeta.live_recording.fabric_config.edge_write_token = "";
1065
+ _context6.next = 55;
1066
+ return this.ReplaceMetadata({
1067
+ libraryId: libraryId,
1068
+ objectId: objectId,
1069
+ writeToken: edgeWriteToken,
1070
+ metadata: edgeMeta
1071
+ });
1072
+ case 55:
1073
+ _context6.next = 57;
1074
+ return this.FinalizeContentObject({
1075
+ libraryId: libraryId,
1076
+ objectId: objectId,
1077
+ writeToken: edgeWriteToken,
1078
+ commitMessage: "Finalize live stream - stop time " + edgeMeta.recording_stop_time,
1079
+ publish: false // Don't publish this version because it is not currently useful
1080
+ });
1081
+ case 57:
1082
+ fin = _context6.sent;
1083
+ return _context6.abrupt("return", {
1084
+ fin: fin,
1085
+ name: name,
1086
+ edge_write_token: edgeWriteToken,
1087
+ state: "terminated"
1088
+ });
1089
+ case 61:
1090
+ _context6.prev = 61;
1091
+ _context6.t1 = _context6["catch"](1);
1092
+ console.error(_context6.t1);
1093
+ case 64:
1094
+ case "end":
1095
+ return _context6.stop();
1096
+ }
1097
+ }, _callee6, this, [[1, 61], [27, 32]]);
1098
+ }));
1099
+ return function (_x6) {
1100
+ return _ref12.apply(this, arguments);
1101
+ };
1102
+ }();
796
1103
 
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
- // }
1104
+ /**
1105
+ * Initialize the stream object
1106
+ *
1107
+ * @methodGroup Live Stream
1108
+ * @namedParams
1109
+ * @param {string} name - Object ID or name of the live stream object
1110
+ * @param {boolean=} drm - If specified, playout will be DRM protected
1111
+ * @param {string=} format - Specify the list of playout formats and DRM to support,
1112
+ comma-separated (hls-clear, hls-aes128, hls-sample-aes,
1113
+ hls-fairplay)
1114
+ *
1115
+ * @return {Promise<Object>} - The name, object ID, and state of the stream
1116
+ */
1117
+ exports.StreamInitialize = /*#__PURE__*/function () {
1118
+ var _ref14 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee7(_ref13) {
1119
+ var name, _ref13$drm, drm, format, contentTypes, typeAbrMaster, typeLiveStream, i, key, res;
1120
+ return _regeneratorRuntime.wrap(function _callee7$(_context7) {
1121
+ while (1) switch (_context7.prev = _context7.next) {
1122
+ case 0:
1123
+ name = _ref13.name, _ref13$drm = _ref13.drm, drm = _ref13$drm === void 0 ? false : _ref13$drm, format = _ref13.format;
1124
+ _context7.next = 3;
1125
+ return this.ContentTypes();
1126
+ case 3:
1127
+ contentTypes = _context7.sent;
1128
+ for (i = 0; i < Object.keys(contentTypes).length; i++) {
1129
+ key = Object.keys(contentTypes)[i];
1130
+ if (contentTypes[key].name.includes("ABR Master") || contentTypes[key].name.includes("Title")) {
1131
+ typeAbrMaster = contentTypes[key].hash;
1132
+ }
1133
+ if (contentTypes[key].name.includes("Live Stream")) {
1134
+ typeLiveStream = contentTypes[key].hash;
1135
+ }
1136
+ }
1137
+ if (!(typeAbrMaster === undefined || typeLiveStream === undefined)) {
1138
+ _context7.next = 8;
1139
+ break;
1140
+ }
1141
+ console.log("ERROR - unable to find content types", "ABR Master", typeAbrMaster, "Live Stream", typeLiveStream);
1142
+ return _context7.abrupt("return", {});
1143
+ case 8:
1144
+ _context7.next = 10;
1145
+ return this.StreamSetOfferingAndDRM({
1146
+ name: name,
1147
+ typeAbrMaster: typeAbrMaster,
1148
+ typeLiveStream: typeLiveStream,
1149
+ drm: drm,
1150
+ format: format
1151
+ });
1152
+ case 10:
1153
+ res = _context7.sent;
1154
+ return _context7.abrupt("return", res);
1155
+ case 12:
1156
+ case "end":
1157
+ return _context7.stop();
1158
+ }
1159
+ }, _callee7, this);
1160
+ }));
1161
+ return function (_x7) {
1162
+ return _ref14.apply(this, arguments);
1163
+ };
1164
+ }();
1165
+
1166
+ /**
1167
+ * Set the Live Stream offering
1168
+ *
1169
+ * @methodGroup Live Stream
1170
+ * @namedParams
1171
+ * @param {string} name - Object ID or name of the live stream object
1172
+ * @param {string=} typeAbrMaster - Content type hash
1173
+ * @param {string=} typeLiveStream - Content type hash
1174
+ * @param {boolean=} drm - If specified, DRM will be applied to the stream
1175
+ * @param {string=} format - A list of playout formats and DRM to support, comma-separated
1176
+ * (hls-clear, hls-aes128, hls-sample-aes, hls-fairplay). If specified,
1177
+ * this will take precedence over the drm value
1178
+ *
1179
+ * @return {Promise<Object>} - The name, object ID, and state of the stream
1180
+ */
1181
+ exports.StreamSetOfferingAndDRM = /*#__PURE__*/function () {
1182
+ var _ref16 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee8(_ref15) {
1183
+ 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;
1184
+ return _regeneratorRuntime.wrap(function _callee8$(_context8) {
1185
+ while (1) switch (_context8.prev = _context8.next) {
1186
+ case 0:
1187
+ name = _ref15.name, typeAbrMaster = _ref15.typeAbrMaster, typeLiveStream = _ref15.typeLiveStream, _ref15$drm = _ref15.drm, drm = _ref15$drm === void 0 ? false : _ref15$drm, format = _ref15.format;
1188
+ _context8.next = 3;
1189
+ return this.StreamStatus({
1190
+ name: name
1191
+ });
1192
+ case 3:
1193
+ status = _context8.sent;
1194
+ if (!(status.state != "inactive" && status.state != "stopped")) {
1195
+ _context8.next = 6;
1196
+ break;
1197
+ }
1198
+ return _context8.abrupt("return", {
1199
+ state: status.state,
1200
+ error: "stream still active - must terminate first"
1201
+ });
1202
+ case 6:
1203
+ objectId = status.object_id;
1204
+ console.log("INIT: ", name, objectId);
1205
+ aBitRate = 128000;
1206
+ aChannels = 2;
1207
+ aSampleRate = 48000;
1208
+ aStreamIndex = 1;
1209
+ aTimeBase = "1/48000";
1210
+ aChannelLayout = "stereo";
1211
+ vBitRate = 14000000;
1212
+ vHeight = 720;
1213
+ vStreamIndex = 0;
1214
+ vWidth = 1280;
1215
+ vDisplayAspectRatio = "16/9";
1216
+ vFrameRate = "30000/1001";
1217
+ vTimeBase = "1/30000"; // "1/16000";
1218
+ abrProfile = require("../abr_profiles/abr_profile_live_drm.js");
1219
+ playoutFormats = abrProfile.playout_formats;
1220
+ if (!format) {
1221
+ _context8.next = 39;
1222
+ break;
1223
+ }
1224
+ drm = true; // Override DRM parameter
1225
+ playoutFormats = {};
1226
+ formats = format.split(",");
1227
+ i = 0;
1228
+ case 28:
1229
+ if (!(i < formats.length)) {
1230
+ _context8.next = 37;
1231
+ break;
1232
+ }
1233
+ if (!(formats[i] === "hls-clear")) {
1234
+ _context8.next = 33;
1235
+ break;
1236
+ }
1237
+ abrProfile.drm_optional = true;
1238
+ playoutFormats["hls-clear"] = {
1239
+ "drm": null,
1240
+ "protocol": {
1241
+ "type": "ProtoHls"
1242
+ }
1243
+ };
1244
+ return _context8.abrupt("continue", 34);
1245
+ case 33:
1246
+ playoutFormats[formats[i]] = abrProfile.playout_formats[formats[i]];
1247
+ case 34:
1248
+ i++;
1249
+ _context8.next = 28;
1250
+ break;
1251
+ case 37:
1252
+ _context8.next = 40;
1253
+ break;
1254
+ case 39:
1255
+ if (!drm) {
1256
+ abrProfile.drm_optional = true;
1257
+ playoutFormats = {
1258
+ "hls-clear": {
1259
+ "drm": null,
1260
+ "protocol": {
1261
+ "type": "ProtoHls"
1262
+ }
1263
+ }
1264
+ };
1265
+ }
1266
+ case 40:
1267
+ abrProfile.playout_formats = playoutFormats;
1268
+ _context8.next = 43;
1269
+ return this.ContentObjectLibraryId({
1270
+ objectId: objectId
1271
+ });
1272
+ case 43:
1273
+ libraryId = _context8.sent;
1274
+ _context8.prev = 44;
1275
+ _context8.next = 47;
1276
+ return this.ContentObjectMetadata({
1277
+ libraryId: libraryId,
1278
+ objectId: objectId
1279
+ });
1280
+ case 47:
1281
+ mainMeta = _context8.sent;
1282
+ fabURI = mainMeta.live_recording.fabric_config.ingress_node_api; // Support both hostname and URL ingress_node_api
1283
+ if (!fabURI.startsWith("http")) {
1284
+ // Assume https
1285
+ fabURI = "https://" + fabURI;
1286
+ }
1287
+ this.SetNodes({
1288
+ fabricURIs: [fabURI]
1289
+ });
1290
+ streamUrl = mainMeta.live_recording.recording_config.recording_params.origin_url;
1291
+ _context8.next = 54;
1292
+ return StreamGenerateOffering({
1293
+ client: this,
1294
+ libraryId: libraryId,
1295
+ objectId: objectId,
1296
+ typeAbrMaster: typeAbrMaster,
1297
+ typeLiveStream: typeLiveStream,
1298
+ streamUrl: streamUrl,
1299
+ abrProfile: abrProfile,
1300
+ aBitRate: aBitRate,
1301
+ aChannels: aChannels,
1302
+ aSampleRate: aSampleRate,
1303
+ aStreamIndex: aStreamIndex,
1304
+ aTimeBase: aTimeBase,
1305
+ aChannelLayout: aChannelLayout,
1306
+ vBitRate: vBitRate,
1307
+ vHeight: vHeight,
1308
+ vStreamIndex: vStreamIndex,
1309
+ vWidth: vWidth,
1310
+ vDisplayAspectRatio: vDisplayAspectRatio,
1311
+ vFrameRate: vFrameRate,
1312
+ vTimeBase: vTimeBase
1313
+ });
1314
+ case 54:
1315
+ console.log("Finished generating offering");
1316
+ return _context8.abrupt("return", {
1317
+ name: name,
1318
+ object_id: objectId,
1319
+ state: "initialized"
1320
+ });
1321
+ case 58:
1322
+ _context8.prev = 58;
1323
+ _context8.t0 = _context8["catch"](44);
1324
+ console.error(_context8.t0);
1325
+ case 61:
1326
+ case "end":
1327
+ return _context8.stop();
1328
+ }
1329
+ }, _callee8, this, [[44, 58]]);
1330
+ }));
1331
+ return function (_x8) {
1332
+ return _ref16.apply(this, arguments);
1333
+ };
1334
+ }();
1335
+
1336
+ /**
1337
+ * Add a content insertion entry
1338
+ *
1339
+ * @methodGroup Live Stream
1340
+ * @namedParams
1341
+ * @param {string} name - Object ID or name of the live stream object
1342
+ * @param {number} insertionTime - Time in seconds (float)
1343
+ * @param {boolean=} sinceStart - If specified, time specified will be elapsed seconds
1344
+ * since stream start, otherwise, time will be elapsed since epoch
1345
+ * @param {number=} duration - Time in seconds (float). Default: 20.0
1346
+ * @param {string} targetHash - The target content object hash (playable)
1347
+ * @param {boolean=} remove - If specified, will remove the inseration at the exact 'time' (instead of adding)
1348
+ *
1349
+ * @return {Promise<Object>} - Insertions, as well as any errors from bad insertions
1350
+ */
1351
+ exports.StreamInsertion = /*#__PURE__*/function () {
1352
+ var _ref18 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee9(_ref17) {
1353
+ 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;
1354
+ return _regeneratorRuntime.wrap(function _callee9$(_context9) {
1355
+ while (1) switch (_context9.prev = _context9.next) {
1356
+ case 0:
1357
+ 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;
1358
+ _context9.next = 3;
1359
+ return this.ContentObjectMetadata({
1360
+ versionHash: targetHash,
1361
+ metadataSubtree: "/offerings/default"
1362
+ });
1363
+ case 3:
1364
+ offeringMeta = _context9.sent;
1365
+ insertionInfo = {
1366
+ duration_sec: 0 // Minimum of video and audio duration
1367
+ };
1368
+
1369
+ ["video", "audio"].forEach(function (mt) {
1370
+ var stream = offeringMeta.media_struct.streams[mt];
1371
+ insertionInfo[mt] = {
1372
+ seg_duration_sec: stream.optimum_seg_dur["float"],
1373
+ duration_sec: stream.duration["float"],
1374
+ frame_rate_rat: stream.rate
1375
+ };
1376
+ if (insertionInfo.duration_sec === 0 || stream.duration["float"] < insertionInfo.duration_sec) {
1377
+ insertionInfo.duration_sec = stream.duration["float"];
1378
+ }
1379
+ });
1380
+ audioAbrDuration = insertionInfo.audio.seg_duration_sec;
1381
+ videoAbrDuration = insertionInfo.video.seg_duration_sec;
1382
+ if (!(audioAbrDuration === 0 || videoAbrDuration === 0)) {
1383
+ _context9.next = 10;
1384
+ break;
1385
+ }
1386
+ throw new Error("Bad segment duration hash:", targetHash);
1387
+ case 10:
1388
+ if (!(duration === undefined)) {
1389
+ _context9.next = 14;
1390
+ break;
1391
+ }
1392
+ duration = insertionInfo.duration_sec; // Use full duration of the insertion
1393
+ _context9.next = 16;
1394
+ break;
1395
+ case 14:
1396
+ if (!(duration > insertionInfo.duration_sec)) {
1397
+ _context9.next = 16;
1398
+ break;
1399
+ }
1400
+ throw new Error("Bad duration - larger than insertion object duration", insertionInfo.duration_sec);
1401
+ case 16:
1402
+ _context9.next = 18;
1403
+ return this.LoadConf({
1404
+ name: name
1405
+ });
1406
+ case 18:
1407
+ conf = _context9.sent;
1408
+ _context9.next = 21;
1409
+ return this.ContentObjectLibraryId({
1410
+ objectId: conf.objectId
1411
+ });
1412
+ case 21:
1413
+ libraryId = _context9.sent;
1414
+ objectId = conf.objectId;
1415
+ _context9.next = 25;
1416
+ return this.ContentObjectMetadata({
1417
+ libraryId: libraryId,
1418
+ objectId: conf.objectId
1419
+ });
1420
+ case 25:
1421
+ mainMeta = _context9.sent;
1422
+ fabURI = mainMeta.live_recording.fabric_config.ingress_node_api; // Support both hostname and URL ingress_node_api
1423
+ if (!fabURI.startsWith("http")) {
1424
+ // Assume https
1425
+ fabURI = "https://" + fabURI;
1426
+ }
1427
+ this.SetNodes({
1428
+ fabricURIs: [fabURI]
1429
+ });
1430
+ edgeWriteToken = mainMeta.live_recording.fabric_config.edge_write_token;
1431
+ _context9.next = 32;
1432
+ return this.ContentObjectMetadata({
1433
+ libraryId: libraryId,
1434
+ objectId: conf.objectId,
1435
+ writeToken: edgeWriteToken
1436
+ });
1437
+ case 32:
1438
+ edgeMeta = _context9.sent;
1439
+ // Find stream start time (from the most recent recording section)
1440
+ recordings = edgeMeta.live_recording.recordings;
1441
+ sequence = 1;
1442
+ streamStartTime = 0;
1443
+ if (recordings != undefined && recordings.recording_sequence != undefined) {
1444
+ // We have at least one recording - check if still active
1445
+ sequence = recordings.recording_sequence;
1446
+ period = recordings.live_offering[sequence - 1];
1447
+ if (period.end_time_epoch_sec > 0) {
1448
+ // The last period is closed - apply insertions to the next period
1449
+ sequence++;
1450
+ } else {
1451
+ // The period is active
1452
+ streamStartTime = period.start_time_epoch_sec;
1453
+ }
1454
+ }
1455
+ if (!(streamStartTime === 0)) {
1456
+ _context9.next = 40;
1457
+ break;
1458
+ }
1459
+ if (!(sinceStart === false)) {
1460
+ _context9.next = 40;
1461
+ break;
1462
+ }
1463
+ throw new Error("Stream not running - must use 'time since start'");
1464
+ case 40:
1465
+ // Find the current period playout configuration
1466
+ if (edgeMeta.live_recording.playout_config.interleaves === undefined) {
1467
+ edgeMeta.live_recording.playout_config.interleaves = {};
1468
+ }
1469
+ if (edgeMeta.live_recording.playout_config.interleaves[sequence] === undefined) {
1470
+ edgeMeta.live_recording.playout_config.interleaves[sequence] = [];
1471
+ }
1472
+ playoutConfig = edgeMeta.live_recording.playout_config;
1473
+ insertions = playoutConfig.interleaves[sequence];
1474
+ res = {};
1475
+ if (!sinceStart) {
1476
+ insertionTime = insertionTime - streamStartTime;
1477
+ }
820
1478
 
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
- // }
1479
+ // Assume insertions are sorted by insertion time
1480
+ errs = [];
1481
+ currentTime = -1;
1482
+ insertionDone = false;
1483
+ newInsertion = {
1484
+ insertion_time: insertionTime,
1485
+ duration: duration,
1486
+ audio_abr_duration: audioAbrDuration,
1487
+ video_abr_duration: videoAbrDuration,
1488
+ playout: "/qfab/" + targetHash + "/rep/playout" // TO FIX - should be a link
1489
+ };
1490
+ i = 0;
1491
+ case 51:
1492
+ if (!(i < insertions.length)) {
1493
+ _context9.next = 66;
1494
+ break;
1495
+ }
1496
+ if (insertions[i].insertion_time <= currentTime) {
1497
+ // Bad insertion - must be later than current time
1498
+ append(errs, "Bad insertion - time:", insertions[i].insertion_time);
1499
+ }
1500
+ if (!remove) {
1501
+ _context9.next = 59;
1502
+ break;
1503
+ }
1504
+ if (!(insertions[i].insertion_time === insertionTime)) {
1505
+ _context9.next = 57;
1506
+ break;
1507
+ }
1508
+ insertions.splice(i, 1);
1509
+ return _context9.abrupt("break", 66);
1510
+ case 57:
1511
+ _context9.next = 63;
1512
+ break;
1513
+ case 59:
1514
+ if (!(insertions[i].insertion_time > insertionTime)) {
1515
+ _context9.next = 63;
1516
+ break;
1517
+ }
1518
+ if (i > 0) {
1519
+ insertions = [].concat(_toConsumableArray(insertions.splice(0, i)), [newInsertion], _toConsumableArray(insertions.splice(i)));
1520
+ } else {
1521
+ insertions = [newInsertion].concat(_toConsumableArray(insertions.splice(i)));
1522
+ }
1523
+ insertionDone = true;
1524
+ return _context9.abrupt("break", 66);
1525
+ case 63:
1526
+ i++;
1527
+ _context9.next = 51;
1528
+ break;
1529
+ case 66:
1530
+ if (!remove && !insertionDone) {
1531
+ // Add to the end of the insertions list
1532
+ console.log("Add insertion at the end");
1533
+ insertions = [].concat(_toConsumableArray(insertions), [newInsertion]);
1534
+ }
1535
+ playoutConfig.interleaves[sequence] = insertions;
931
1536
 
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
- // }
1537
+ // Store the new insertions in the write token
1538
+ _context9.next = 70;
1539
+ return this.ReplaceMetadata({
1540
+ libraryId: libraryId,
1541
+ objectId: objectId,
1542
+ writeToken: edgeWriteToken,
1543
+ metadataSubtree: "/live_recording/playout_config",
1544
+ metadata: edgeMeta.live_recording.playout_config
1545
+ });
1546
+ case 70:
1547
+ res.errors = errs;
1548
+ res.insertions = insertions;
1549
+ return _context9.abrupt("return", res);
1550
+ case 73:
1551
+ case "end":
1552
+ return _context9.stop();
1553
+ }
1554
+ }, _callee9, this);
1555
+ }));
1556
+ return function (_x9) {
1557
+ return _ref18.apply(this, arguments);
1558
+ };
1559
+ }();
1091
1560
 
1561
+ /**
1562
+ * Load cached stream configuration
1563
+ *
1564
+ * @methodGroup Live Stream
1565
+ * @namedParams
1566
+ * @param {string} name - Object ID or name of the live stream object
1567
+ *
1568
+ * @return {Promise<Object>} - The configuration of the stream
1569
+ */
1092
1570
  exports.LoadConf = /*#__PURE__*/function () {
1093
- var _ref10 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee5(_ref9) {
1571
+ var _ref20 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee10(_ref19) {
1094
1572
  var name, streamsBuf, streams, conf;
1095
- return _regeneratorRuntime.wrap(function _callee5$(_context5) {
1096
- while (1) switch (_context5.prev = _context5.next) {
1573
+ return _regeneratorRuntime.wrap(function _callee10$(_context10) {
1574
+ while (1) switch (_context10.prev = _context10.next) {
1097
1575
  case 0:
1098
- name = _ref9.name;
1576
+ name = _ref19.name;
1099
1577
  if (!name.startsWith("iq__")) {
1100
- _context5.next = 3;
1578
+ _context10.next = 3;
1101
1579
  break;
1102
1580
  }
1103
- return _context5.abrupt("return", {
1581
+ return _context10.abrupt("return", {
1104
1582
  name: name,
1105
1583
  objectId: name
1106
1584
  });
1107
1585
  case 3:
1108
- _context5.prev = 3;
1586
+ _context10.prev = 3;
1109
1587
  streamsBuf = fs.readFileSync(path.resolve(__dirname, "../liveconf.json"));
1110
- _context5.next = 11;
1588
+ _context10.next = 11;
1111
1589
  break;
1112
1590
  case 7:
1113
- _context5.prev = 7;
1114
- _context5.t0 = _context5["catch"](3);
1591
+ _context10.prev = 7;
1592
+ _context10.t0 = _context10["catch"](3);
1115
1593
  console.log("Stream name must be a QID or a label in liveconf.json");
1116
- return _context5.abrupt("return", {});
1594
+ return _context10.abrupt("return", {});
1117
1595
  case 11:
1118
1596
  streams = JSON.parse(streamsBuf);
1119
1597
  conf = streams[name];
1120
1598
  if (!(conf === null)) {
1121
- _context5.next = 16;
1599
+ _context10.next = 16;
1122
1600
  break;
1123
1601
  }
1124
1602
  console.log("Bad name: ", name);
1125
- return _context5.abrupt("return", {});
1603
+ return _context10.abrupt("return", {});
1126
1604
  case 16:
1127
- return _context5.abrupt("return", conf);
1605
+ return _context10.abrupt("return", conf);
1128
1606
  case 17:
1129
1607
  case "end":
1130
- return _context5.stop();
1608
+ return _context10.stop();
1131
1609
  }
1132
- }, _callee5, null, [[3, 7]]);
1610
+ }, _callee10, null, [[3, 7]]);
1133
1611
  }));
1134
- return function (_x5) {
1135
- return _ref10.apply(this, arguments);
1612
+ return function (_x10) {
1613
+ return _ref20.apply(this, arguments);
1136
1614
  };
1137
1615
  }();
1138
1616
 
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
1617
  /**
1296
1618
  * Configure the stream
1297
1619
  *
1298
1620
  * @methodGroup Live Stream
1299
1621
  * @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'
1622
+ * @param {string} name - Object ID or name of the live stream object
1623
+ * @param {Object=} customSettings - Additional options to customize configuration settings
1624
+ * - audioBitrate
1625
+ * - audioIndex
1626
+ * - partTtl
1627
+ * - channelLayout
1307
1628
  *
1308
- * @return {Object} - The status response for the stream
1629
+ * @return {Promise<Object>} - The status response for the stream
1309
1630
  *
1310
1631
  */
1311
1632
  exports.StreamConfig = /*#__PURE__*/function () {
1312
- 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;
1314
- return _regeneratorRuntime.wrap(function _callee6$(_context6) {
1315
- while (1) switch (_context6.prev = _context6.next) {
1633
+ var _ref22 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee11(_ref21) {
1634
+ var name, _ref21$customSettings, customSettings, conf, status, libraryId, mainMeta, userConfig, hostName, streamUrl, nodes, node, endpoint, probe, controller, timeoutId, probeUrl, lc, liveRecordingConfigStr, liveRecordingConfig, e, writeToken;
1635
+ return _regeneratorRuntime.wrap(function _callee11$(_context11) {
1636
+ while (1) switch (_context11.prev = _context11.next) {
1316
1637
  case 0:
1317
- name = _ref11.name, customSettings = _ref11.customSettings;
1318
- _context6.next = 3;
1638
+ name = _ref21.name, _ref21$customSettings = _ref21.customSettings, customSettings = _ref21$customSettings === void 0 ? {} : _ref21$customSettings;
1639
+ _context11.next = 3;
1319
1640
  return this.LoadConf({
1320
1641
  name: name
1321
1642
  });
1322
1643
  case 3:
1323
- conf = _context6.sent;
1644
+ conf = _context11.sent;
1324
1645
  status = {
1325
1646
  name: name
1326
1647
  };
1327
- _context6.next = 7;
1648
+ _context11.next = 7;
1328
1649
  return this.ContentObjectLibraryId({
1329
1650
  objectId: conf.objectId
1330
1651
  });
1331
1652
  case 7:
1332
- libraryId = _context6.sent;
1653
+ libraryId = _context11.sent;
1333
1654
  status.library_id = libraryId;
1334
1655
  status.object_id = conf.objectId;
1335
- _context6.next = 12;
1656
+ _context11.next = 12;
1336
1657
  return this.ContentObjectMetadata({
1337
1658
  libraryId: libraryId,
1338
1659
  objectId: conf.objectId
1339
1660
  });
1340
1661
  case 12:
1341
- mainMeta = _context6.sent;
1662
+ mainMeta = _context11.sent;
1342
1663
  userConfig = mainMeta.live_recording_config;
1343
1664
  status.user_config = userConfig;
1344
1665
 
@@ -1346,18 +1667,18 @@ exports.StreamConfig = /*#__PURE__*/function () {
1346
1667
  hostName = userConfig.url.replace("udp://", "").replace("rtmp://", "").split(":")[0];
1347
1668
  streamUrl = new URL(userConfig.url);
1348
1669
  console.log("Retrieving nodes...");
1349
- _context6.next = 20;
1670
+ _context11.next = 20;
1350
1671
  return this.SpaceNodes({
1351
1672
  matchEndpoint: hostName
1352
1673
  });
1353
1674
  case 20:
1354
- nodes = _context6.sent;
1675
+ nodes = _context11.sent;
1355
1676
  if (!(nodes.length < 1)) {
1356
- _context6.next = 24;
1677
+ _context11.next = 24;
1357
1678
  break;
1358
1679
  }
1359
1680
  status.error = "No node matching stream URL " + streamUrl.href;
1360
- return _context6.abrupt("return", status);
1681
+ return _context11.abrupt("return", status);
1361
1682
  case 24:
1362
1683
  node = nodes[0];
1363
1684
  status.node = node;
@@ -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 = 31;
1697
+ _context11.next = 34;
1377
1698
  return this.Rep({
1378
1699
  libraryId: libraryId,
1379
1700
  objectId: conf.objectId,
1380
1701
  rep: "probe"
1381
1702
  });
1382
1703
  case 34:
1383
- probeUrl = _context6.sent;
1384
- _context6.t0 = this.utils;
1385
- _context6.next = 38;
1704
+ probeUrl = _context11.sent;
1705
+ _context11.t0 = this.utils;
1706
+ _context11.next = 38;
1386
1707
  return HttpClient.Fetch(probeUrl, {
1387
1708
  body: JSON.stringify({
1388
1709
  "filename": streamUrl.href,
@@ -1392,32 +1713,32 @@ exports.StreamConfig = /*#__PURE__*/function () {
1392
1713
  signal: controller.signal
1393
1714
  });
1394
1715
  case 38:
1395
- _context6.t1 = _context6.sent;
1396
- _context6.next = 41;
1397
- return _context6.t0.ResponseToJson.call(_context6.t0, _context6.t1);
1716
+ _context11.t1 = _context11.sent;
1717
+ _context11.next = 41;
1718
+ return _context11.t0.ResponseToJson.call(_context11.t0, _context11.t1);
1398
1719
  case 41:
1399
- probe = _context6.sent;
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 = 45;
1405
1726
  break;
1406
1727
  }
1407
1728
  throw probe.errors[0];
1408
1729
  case 45:
1409
- _context6.next = 54;
1730
+ _context11.next = 54;
1410
1731
  break;
1411
1732
  case 47:
1412
- _context6.prev = 47;
1413
- _context6.t2 = _context6["catch"](31);
1414
- if (!(_context6.t2.code === "ETIMEDOUT")) {
1415
- _context6.next = 53;
1733
+ _context11.prev = 47;
1734
+ _context11.t2 = _context11["catch"](31);
1735
+ if (!(_context11.t2.code === "ETIMEDOUT")) {
1736
+ _context11.next = 53;
1416
1737
  break;
1417
1738
  }
1418
1739
  throw "Stream probe time out - make sure the stream source is available";
1419
1740
  case 53:
1420
- throw _context6.t2;
1741
+ throw _context11.t2;
1421
1742
  case 54:
1422
1743
  console.log("PROBE", probe);
1423
1744
  probe.format.filename = streamUrl.href;
@@ -1434,15 +1755,15 @@ exports.StreamConfig = /*#__PURE__*/function () {
1434
1755
  console.log("CONFIG", JSON.stringify(liveRecordingConfig.live_recording));
1435
1756
 
1436
1757
  // Store live recording config into the stream object
1437
- _context6.next = 62;
1758
+ _context11.next = 62;
1438
1759
  return this.EditContentObject({
1439
1760
  libraryId: libraryId,
1440
1761
  objectId: conf.objectId
1441
1762
  });
1442
1763
  case 62:
1443
- e = _context6.sent;
1764
+ e = _context11.sent;
1444
1765
  writeToken = e.write_token;
1445
- _context6.next = 66;
1766
+ _context11.next = 66;
1446
1767
  return this.ReplaceMetadata({
1447
1768
  libraryId: libraryId,
1448
1769
  objectId: conf.objectId,
@@ -1451,7 +1772,7 @@ exports.StreamConfig = /*#__PURE__*/function () {
1451
1772
  metadata: liveRecordingConfig.live_recording
1452
1773
  });
1453
1774
  case 66:
1454
- _context6.next = 68;
1775
+ _context11.next = 68;
1455
1776
  return this.ReplaceMetadata({
1456
1777
  libraryId: libraryId,
1457
1778
  objectId: conf.objectId,
@@ -1460,7 +1781,7 @@ exports.StreamConfig = /*#__PURE__*/function () {
1460
1781
  metadata: probe
1461
1782
  });
1462
1783
  case 68:
1463
- _context6.next = 70;
1784
+ _context11.next = 70;
1464
1785
  return this.FinalizeContentObject({
1465
1786
  libraryId: libraryId,
1466
1787
  objectId: conf.objectId,
@@ -1468,332 +1789,15 @@ exports.StreamConfig = /*#__PURE__*/function () {
1468
1789
  commitMessage: "Apply live stream configuration"
1469
1790
  });
1470
1791
  case 70:
1471
- status.fin = _context6.sent;
1472
- return _context6.abrupt("return", status);
1792
+ status.fin = _context11.sent;
1793
+ return _context11.abrupt("return", status);
1473
1794
  case 72:
1474
1795
  case "end":
1475
- return _context6.stop();
1796
+ return _context11.stop();
1476
1797
  }
1477
- }, _callee6, this, [[31, 47]]);
1798
+ }, _callee11, this, [[31, 47]]);
1478
1799
  }));
1479
- return function (_x6) {
1480
- return _ref12.apply(this, arguments);
1800
+ return function (_x11) {
1801
+ return _ref22.apply(this, arguments);
1481
1802
  };
1482
- }();
1483
-
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
1735
- */
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
- // }
1803
+ }();