@eluvio/elv-client-js 4.0.93 → 4.0.95
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/ElvWalletClient-min.js +7 -7
- package/dist/ElvWalletClient-node-min.js +8 -8
- package/dist/src/walletClient/index.js +11 -7
- package/package.json +1 -1
- package/src/walletClient/index.js +6 -4
- package/testScripts/BasicObjectOperations.js +1 -1
- package/testScripts/OfferingDownloadMedia.js +291 -0
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
var _slicedToArray = require("@babel/runtime/helpers/slicedToArray");
|
|
2
|
+
var _objectWithoutProperties = require("@babel/runtime/helpers/objectWithoutProperties");
|
|
2
3
|
var _defineProperty = require("@babel/runtime/helpers/defineProperty");
|
|
3
4
|
var _regeneratorRuntime = require("@babel/runtime/regenerator");
|
|
4
5
|
var _typeof = require("@babel/runtime/helpers/typeof");
|
|
5
6
|
var _asyncToGenerator = require("@babel/runtime/helpers/asyncToGenerator");
|
|
6
7
|
var _classCallCheck = require("@babel/runtime/helpers/classCallCheck");
|
|
7
8
|
var _createClass = require("@babel/runtime/helpers/createClass");
|
|
9
|
+
var _excluded = ["code", "address", "type", "authToken", "expiresAt"];
|
|
8
10
|
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
|
|
9
11
|
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
|
|
10
12
|
var _require = require("../ElvClient"),
|
|
@@ -1002,11 +1004,11 @@ var ElvWalletClient = /*#__PURE__*/function () {
|
|
|
1002
1004
|
key: "SetCodeAuth",
|
|
1003
1005
|
value: function () {
|
|
1004
1006
|
var _SetCodeAuth = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee16(_ref15) {
|
|
1005
|
-
var code, address, type, authToken;
|
|
1007
|
+
var code, address, type, authToken, expiresAt, additionalPayload;
|
|
1006
1008
|
return _regeneratorRuntime.wrap(function _callee16$(_context16) {
|
|
1007
1009
|
while (1) switch (_context16.prev = _context16.next) {
|
|
1008
1010
|
case 0:
|
|
1009
|
-
code = _ref15.code, address = _ref15.address, type = _ref15.type, authToken = _ref15.authToken;
|
|
1011
|
+
code = _ref15.code, address = _ref15.address, type = _ref15.type, authToken = _ref15.authToken, expiresAt = _ref15.expiresAt, additionalPayload = _objectWithoutProperties(_ref15, _excluded);
|
|
1010
1012
|
_context16.next = 3;
|
|
1011
1013
|
return Utils.ResponseToJson(this.client.authClient.MakeAuthServiceRequest({
|
|
1012
1014
|
path: UrlJoin("as", "wlt", "login", "session", code),
|
|
@@ -1018,12 +1020,13 @@ var ElvWalletClient = /*#__PURE__*/function () {
|
|
|
1018
1020
|
op: "set",
|
|
1019
1021
|
id: code,
|
|
1020
1022
|
format: "auth_token",
|
|
1021
|
-
payload: JSON.stringify({
|
|
1023
|
+
payload: JSON.stringify(_objectSpread({
|
|
1022
1024
|
addr: Utils.FormatAddress(address),
|
|
1023
1025
|
eth: address ? "ikms".concat(Utils.AddressToHash(address)) : "",
|
|
1024
1026
|
type: type,
|
|
1025
|
-
token: authToken
|
|
1026
|
-
|
|
1027
|
+
token: authToken,
|
|
1028
|
+
expiresAt: expiresAt
|
|
1029
|
+
}, additionalPayload))
|
|
1027
1030
|
}
|
|
1028
1031
|
}));
|
|
1029
1032
|
case 3:
|
|
@@ -1875,11 +1878,11 @@ var ElvWalletClient = /*#__PURE__*/function () {
|
|
|
1875
1878
|
key: "DeployTenant",
|
|
1876
1879
|
value: function () {
|
|
1877
1880
|
var _DeployTenant = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee24(_ref23) {
|
|
1878
|
-
var tenantId, _ref23$tenantSlug, tenantSlug, tenantHash, tenantLink, deployedTenantHash, body, token;
|
|
1881
|
+
var tenantId, _ref23$tenantSlug, tenantSlug, tenantHash, _ref23$environment, environment, tenantLink, deployedTenantHash, body, token;
|
|
1879
1882
|
return _regeneratorRuntime.wrap(function _callee24$(_context24) {
|
|
1880
1883
|
while (1) switch (_context24.prev = _context24.next) {
|
|
1881
1884
|
case 0:
|
|
1882
|
-
tenantId = _ref23.tenantId, _ref23$tenantSlug = _ref23.tenantSlug, tenantSlug = _ref23$tenantSlug === void 0 ? "" : _ref23$tenantSlug, tenantHash = _ref23.tenantHash;
|
|
1885
|
+
tenantId = _ref23.tenantId, _ref23$tenantSlug = _ref23.tenantSlug, tenantSlug = _ref23$tenantSlug === void 0 ? "" : _ref23$tenantSlug, tenantHash = _ref23.tenantHash, _ref23$environment = _ref23.environment, environment = _ref23$environment === void 0 ? "production" : _ref23$environment;
|
|
1883
1886
|
if (tenantHash) {
|
|
1884
1887
|
_context24.next = 11;
|
|
1885
1888
|
break;
|
|
@@ -1913,6 +1916,7 @@ var ElvWalletClient = /*#__PURE__*/function () {
|
|
|
1913
1916
|
case 11:
|
|
1914
1917
|
body = {
|
|
1915
1918
|
content_hash: tenantHash,
|
|
1919
|
+
env: environment,
|
|
1916
1920
|
ts: Date.now()
|
|
1917
1921
|
};
|
|
1918
1922
|
_context24.next = 14;
|
package/package.json
CHANGED
|
@@ -702,7 +702,7 @@ class ElvWalletClient {
|
|
|
702
702
|
return response;
|
|
703
703
|
}
|
|
704
704
|
|
|
705
|
-
async SetCodeAuth({code, address, type, authToken}) {
|
|
705
|
+
async SetCodeAuth({code, address, type, authToken, expiresAt, ...additionalPayload}) {
|
|
706
706
|
await Utils.ResponseToJson(
|
|
707
707
|
this.client.authClient.MakeAuthServiceRequest({
|
|
708
708
|
path: UrlJoin("as", "wlt", "login", "session", code),
|
|
@@ -718,7 +718,9 @@ class ElvWalletClient {
|
|
|
718
718
|
addr: Utils.FormatAddress(address),
|
|
719
719
|
eth: address ? `ikms${Utils.AddressToHash(address)}` : "",
|
|
720
720
|
type,
|
|
721
|
-
token: authToken
|
|
721
|
+
token: authToken,
|
|
722
|
+
expiresAt,
|
|
723
|
+
...additionalPayload
|
|
722
724
|
})
|
|
723
725
|
}
|
|
724
726
|
})
|
|
@@ -1386,7 +1388,7 @@ class ElvWalletClient {
|
|
|
1386
1388
|
}
|
|
1387
1389
|
}
|
|
1388
1390
|
|
|
1389
|
-
async DeployTenant({tenantId, tenantSlug="", tenantHash}) {
|
|
1391
|
+
async DeployTenant({tenantId, tenantSlug="", tenantHash, environment="production"}) {
|
|
1390
1392
|
if(!tenantHash) {
|
|
1391
1393
|
const tenantLink = await this.client.ContentObjectMetadata({
|
|
1392
1394
|
libraryId: this.mainSiteLibraryId,
|
|
@@ -1410,7 +1412,7 @@ class ElvWalletClient {
|
|
|
1410
1412
|
tenantHash = await this.client.LatestVersionHash({versionHash: deployedTenantHash});
|
|
1411
1413
|
}
|
|
1412
1414
|
|
|
1413
|
-
const body = { content_hash: tenantHash, ts: Date.now() };
|
|
1415
|
+
const body = { content_hash: tenantHash, env: environment, ts: Date.now() };
|
|
1414
1416
|
const token = await this.client.Sign(JSON.stringify(body));
|
|
1415
1417
|
await this.client.authClient.MakeAuthServiceRequest({
|
|
1416
1418
|
path: UrlJoin("as", "tnt", "config", tenantId, "metadata"),
|
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
/* eslint-disable no-console */
|
|
2
|
+
const ScriptBase = require("./parentClasses/ScriptBase");
|
|
3
|
+
const utils = require("../src/Utils");
|
|
4
|
+
const Fraction = require("fraction.js");
|
|
5
|
+
const {JSONPath} = require("jsonpath-plus");
|
|
6
|
+
const fs = require("fs");
|
|
7
|
+
const path = require("path");
|
|
8
|
+
const { execSync } = require("child_process");
|
|
9
|
+
|
|
10
|
+
class OfferingDownloadMedia2 extends ScriptBase {
|
|
11
|
+
|
|
12
|
+
async body(){
|
|
13
|
+
|
|
14
|
+
let objectId=this.args.objectId;
|
|
15
|
+
const versionHash=this.args.versionHash;
|
|
16
|
+
const offeringKey=this.args.offeringKey;
|
|
17
|
+
const streamKey=this.args.streamKey;
|
|
18
|
+
const startTime=this.args.startTime;
|
|
19
|
+
let endTime=this.args.endTime;
|
|
20
|
+
const out=this.args.out;
|
|
21
|
+
|
|
22
|
+
if(!objectId && !versionHash) throw new Error("Require object-id or object-hash to be provided");
|
|
23
|
+
if(!objectId) {
|
|
24
|
+
objectId = utils.DecodeVersionHash(versionHash).objectId;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if(startTime < 0) {
|
|
28
|
+
throw new Error(`start time provided needs to be greater than 0: start=${startTime}s`);
|
|
29
|
+
}
|
|
30
|
+
if(startTime >= endTime) {
|
|
31
|
+
throw new Error(`end time needs to be greater than start time, values provided: start=${startTime}s, end=${endTime}s`);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const client=await this.client();
|
|
35
|
+
const libraryId=await client.ContentObjectLibraryId({objectId, versionHash});
|
|
36
|
+
|
|
37
|
+
// get object metadata
|
|
38
|
+
const metadata = await client.ContentObjectMetadata({ libraryId, objectId });
|
|
39
|
+
|
|
40
|
+
const offeringMetadata=JSONPath({
|
|
41
|
+
json: metadata,
|
|
42
|
+
path: `offerings.${offeringKey}`,
|
|
43
|
+
wrap: false
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
const transcodesMetadata=JSONPath({
|
|
47
|
+
json:metadata,
|
|
48
|
+
path: "transcodes"
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
// Retrieve stream metadata from transcodes or offering metadata
|
|
52
|
+
// Create a map of streamKey => stream metadata
|
|
53
|
+
const streamsMap = Object.fromEntries(
|
|
54
|
+
Object.keys(offeringMetadata.playout.streams).map(streamKey => {
|
|
55
|
+
const info = this.getStreamInfo(offeringMetadata, transcodesMetadata, streamKey);
|
|
56
|
+
if (info === undefined) {
|
|
57
|
+
console.log(`StreamInfo returned undefined for streamKey: ${streamKey}`);
|
|
58
|
+
}
|
|
59
|
+
return [streamKey, info || {}];
|
|
60
|
+
})
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
let streamKeyArray = streamKey.split(",").map(key => key.trim()); // trim() to remove any extra spaces
|
|
64
|
+
const streamsMapKeys = new Set(Object.keys(streamsMap));
|
|
65
|
+
|
|
66
|
+
// Filter the streamKeyArray to only include keys present in streamsMap
|
|
67
|
+
streamKeyArray = streamKeyArray.filter(key => {
|
|
68
|
+
if (!streamsMapKeys.has(key)) {
|
|
69
|
+
console.warn(`Warning: Stream key "${key}" not found in streamsMap.`);
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
return true;
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
// Retrieve all parts that includes the start and end time for each streamKey
|
|
76
|
+
const partsMap = this.getPartsMap(streamsMap, streamKeyArray, startTime, endTime);
|
|
77
|
+
console.log("PARTS MAP => { parts, minStart, maxEnd } map:", partsMap);
|
|
78
|
+
|
|
79
|
+
// handle directories
|
|
80
|
+
const dirPath=path.resolve(out);
|
|
81
|
+
if(!fs.existsSync(dirPath)) {
|
|
82
|
+
fs.mkdirSync(dirPath, {recursive: true});
|
|
83
|
+
console.log(`Directory created at ${dirPath}`);
|
|
84
|
+
} else {
|
|
85
|
+
console.log(`Directory already exists at ${dirPath}`);
|
|
86
|
+
}
|
|
87
|
+
// create directory for object provided : iq_XXX_start-time_end-time
|
|
88
|
+
const contentObjDirPath = path.join(dirPath, `${objectId}_${this.secondsToHms(startTime, "-")}_${this.secondsToHms(endTime, "-")}`);
|
|
89
|
+
// if(fs.existsSync(contentObjDirPath)) throw new Error(`Directory already exists at ${contentObjDirPath}`);
|
|
90
|
+
// fs.mkdirSync(contentObjDirPath, { recursive: true });
|
|
91
|
+
if(!fs.existsSync(contentObjDirPath)) {
|
|
92
|
+
fs.mkdirSync(contentObjDirPath, { recursive: true });
|
|
93
|
+
console.log(`Directory created at ${contentObjDirPath}`);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const trimmedDirectory = path.join(contentObjDirPath, "trimmed");
|
|
97
|
+
if(!fs.existsSync(trimmedDirectory)) {
|
|
98
|
+
fs.mkdirSync(trimmedDirectory, { recursive: true });
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Download and concatenate the parts for each streamKey
|
|
102
|
+
// Then, trim the concatenated media
|
|
103
|
+
for(const streamKey of Object.keys(partsMap)) {
|
|
104
|
+
const { parts, minStart, maxEnd } = partsMap[streamKey];
|
|
105
|
+
const partsFile = await this.downloadParts(contentObjDirPath, libraryId, objectId, streamKey, parts);
|
|
106
|
+
console.log(`parts file for ${streamKey}: ${partsFile}\n`);
|
|
107
|
+
|
|
108
|
+
// concatenate the parts
|
|
109
|
+
let mediaFile=path.join(contentObjDirPath, `${streamKey}.mp4`);
|
|
110
|
+
let cmd=`ffmpeg -f concat -safe 0 -i ${partsFile} -c copy ${mediaFile}`;
|
|
111
|
+
console.log("Running", cmd);
|
|
112
|
+
try {
|
|
113
|
+
execSync(cmd);
|
|
114
|
+
console.log("Concatenation complete.");
|
|
115
|
+
} catch(error) {
|
|
116
|
+
console.error("Error running ffmpeg:", error);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// trim the parts
|
|
120
|
+
let trimStartTime=null;
|
|
121
|
+
let trimEndTime=null;
|
|
122
|
+
// since new concatenated video starts from 0s
|
|
123
|
+
if(minStart !== null && maxEnd !== null) {
|
|
124
|
+
trimStartTime=startTime - minStart;
|
|
125
|
+
trimEndTime=endTime - minStart;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
let mediaTrimmedFile=path.join(trimmedDirectory, `${streamKey}_trimmed.mp4`);
|
|
129
|
+
cmd=`ffmpeg -i ${mediaFile} -ss ${this.secondsToHms(trimStartTime, ":")} -t ${this.secondsToHms(trimEndTime - trimStartTime, ":")} ${mediaTrimmedFile}`;
|
|
130
|
+
console.log("Running", cmd);
|
|
131
|
+
try {
|
|
132
|
+
execSync(cmd);
|
|
133
|
+
console.log(`\nTrimmed ${streamKey} file: ${mediaTrimmedFile}`);
|
|
134
|
+
} catch(error) {
|
|
135
|
+
console.error("Error running ffmpeg:", error);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
console.log("================================================");
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
getStreamInfo(offering, transcodes, streamKey) {
|
|
144
|
+
const reps = offering.playout.streams[streamKey].representations;
|
|
145
|
+
const rep = reps && Object.values(reps).find(r => r.transcode_id);
|
|
146
|
+
return rep && (transcodes[0] && transcodes[0][rep.transcode_id] && transcodes[0][rep.transcode_id].stream) || offering.media_struct.streams[streamKey];
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
getPartsMap(streamsMap, streamKeyArray, startTime, endTime){
|
|
150
|
+
const partsMap = {};
|
|
151
|
+
|
|
152
|
+
streamKeyArray.forEach(key => {
|
|
153
|
+
let sourcesMetadata = streamsMap[key].sources;
|
|
154
|
+
let durationMetadata = streamsMap[key].duration;
|
|
155
|
+
|
|
156
|
+
const totalDuration = new Fraction(durationMetadata.ts).mul(new Fraction(durationMetadata.time_base));
|
|
157
|
+
if (endTime > totalDuration) {
|
|
158
|
+
console.warn(`Warning: end time exceeds total duration. Setting end time to total duration: ${totalDuration}s`);
|
|
159
|
+
endTime = totalDuration;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const sourcesTimeInfo = sourcesMetadata.map(part => {
|
|
163
|
+
const start = new Fraction(part.timeline_start.ts).mul(new Fraction(part.timeline_start.time_base));
|
|
164
|
+
const end = new Fraction(part.timeline_end.ts).mul(new Fraction(part.timeline_end.time_base));
|
|
165
|
+
return {
|
|
166
|
+
start: start.valueOf(),
|
|
167
|
+
end: end.valueOf(),
|
|
168
|
+
source: part.source
|
|
169
|
+
};
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
let parts = [];
|
|
173
|
+
let minStart = null;
|
|
174
|
+
let maxEnd = null;
|
|
175
|
+
sourcesTimeInfo.forEach(item => {
|
|
176
|
+
if(startTime < item.end && endTime > item.start) {
|
|
177
|
+
parts.push(item.source);
|
|
178
|
+
if (minStart === null || item.start < minStart) {
|
|
179
|
+
minStart = item.start;
|
|
180
|
+
}
|
|
181
|
+
if(maxEnd === null || item.end > maxEnd) {
|
|
182
|
+
maxEnd = item.end;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
partsMap[key] = {
|
|
188
|
+
parts,
|
|
189
|
+
minStart,
|
|
190
|
+
maxEnd
|
|
191
|
+
};
|
|
192
|
+
});
|
|
193
|
+
return partsMap;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
async downloadParts(outDir, libraryId, objectId, streamKey, parts) {
|
|
197
|
+
const mtPath=path.join(outDir, streamKey);
|
|
198
|
+
if(!fs.existsSync(mtPath)) {
|
|
199
|
+
fs.mkdirSync(mtPath, {recursive: true});
|
|
200
|
+
console.log(`Directory created at ${mtPath}`);
|
|
201
|
+
} else {
|
|
202
|
+
throw new Error(`Directory already exists at ${mtPath}`);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
const partsFile=path.join(outDir, `parts_${streamKey}.txt`);
|
|
206
|
+
const client=await this.client();
|
|
207
|
+
|
|
208
|
+
console.log("\nDownloading parts...\n");
|
|
209
|
+
for(const [index, partHash] of parts.entries()) {
|
|
210
|
+
let ph=(index + 1).toString().padStart(4, "0") + "." + partHash;
|
|
211
|
+
console.log(`processing ${ph}...`);
|
|
212
|
+
|
|
213
|
+
const buf=await client.DownloadPart({
|
|
214
|
+
libraryId,
|
|
215
|
+
objectId,
|
|
216
|
+
partHash,
|
|
217
|
+
format: "buffer",
|
|
218
|
+
chunked: false,
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
let partFile=path.join(mtPath, ph + ".mp4");
|
|
222
|
+
fs.appendFileSync(partFile, buf, (err) => {
|
|
223
|
+
if(err) {
|
|
224
|
+
console.log(err);
|
|
225
|
+
}
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
fs.appendFileSync(partsFile, `file '${partFile}'\n`, (err) => {
|
|
229
|
+
if(err) {
|
|
230
|
+
console.log(err);
|
|
231
|
+
}
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
return partsFile;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
secondsToHms(seconds, separator) {
|
|
238
|
+
const date=new Date(seconds * 1000);
|
|
239
|
+
const hh=String(date.getUTCHours()).padStart(2, "0");
|
|
240
|
+
const mm=String(date.getUTCMinutes()).padStart(2, "0");
|
|
241
|
+
const ss=String(date.getUTCSeconds()).padStart(2, "0");
|
|
242
|
+
const ms=String(date.getUTCMilliseconds()).padStart(3, "0");
|
|
243
|
+
return `${hh}${separator}${mm}${separator}${ss}.${ms}`;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
header() {
|
|
247
|
+
return `Downloading parts from startTime: ${this.args.startTime}s to endTime: ${this.args.endTime}s`;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
options() {
|
|
251
|
+
return super.options()
|
|
252
|
+
.option("objectId", {
|
|
253
|
+
alias: "object-id",
|
|
254
|
+
describe: "Object ID (should start with 'iq__')",
|
|
255
|
+
type: "string"
|
|
256
|
+
})
|
|
257
|
+
.option("versionHash", {
|
|
258
|
+
alias: "version-hash",
|
|
259
|
+
describe: "Object Version Hash (should start with 'hq__')",
|
|
260
|
+
type: "string"
|
|
261
|
+
})
|
|
262
|
+
.option("offeringKey", {
|
|
263
|
+
describe: "offering key",
|
|
264
|
+
type: "string",
|
|
265
|
+
default: "default",
|
|
266
|
+
})
|
|
267
|
+
.option("streamKey", {
|
|
268
|
+
describe: "comma separated list of offerings stream key",
|
|
269
|
+
type: "string",
|
|
270
|
+
default: "video",
|
|
271
|
+
})
|
|
272
|
+
.option("startTime", {
|
|
273
|
+
describe: "start time to retrieve parts in seconds",
|
|
274
|
+
demandOption: true,
|
|
275
|
+
type: "number",
|
|
276
|
+
})
|
|
277
|
+
.option("endTime", {
|
|
278
|
+
describe: "end time to retrieve parts in seconds",
|
|
279
|
+
demandOption: true,
|
|
280
|
+
type: "number",
|
|
281
|
+
})
|
|
282
|
+
.option("out",{
|
|
283
|
+
describe: "output directory",
|
|
284
|
+
type: "string",
|
|
285
|
+
default: "./out",
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
const script = new OfferingDownloadMedia2();
|
|
291
|
+
script.run();
|