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