@eluvio/elv-client-js 4.0.57 → 4.0.59

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eluvio/elv-client-js",
3
- "version": "4.0.57",
3
+ "version": "4.0.59",
4
4
  "description": "Javascript client for the Eluvio Content Fabric",
5
5
  "main": "src/index.js",
6
6
  "author": "Kevin Talmadge",
package/src/Utils.js CHANGED
@@ -743,12 +743,26 @@ const Utils = {
743
743
  }
744
744
  },
745
745
 
746
- LiveHLSJSSettings({lowLatency=false}) {
746
+ LiveHLSJSSettings({lowLatency=false, ultraLowLatency=false}) {
747
747
  const isSafari =
748
748
  typeof window !== "undefined" &&
749
749
  typeof window.navigator !== "undefined" &&
750
750
  /^((?!chrome|android).)*safari/i.test(window.navigator.userAgent);
751
751
 
752
+ if(ultraLowLatency && !isSafari) {
753
+ return {
754
+ "capLevelToPlayerSize": false,
755
+ "enableWorker": true,
756
+ "lowLatencyMode": true,
757
+ "maxBufferLength": 4,
758
+ "backBufferLength": 4,
759
+ "liveSyncDuration": 4,
760
+ "liveMaxLatencyDuration": 5,
761
+ "liveDurationInfinity": false,
762
+ "highBufferWatchdogPeriod": 1
763
+ };
764
+ }
765
+
752
766
  return {
753
767
  "enableWorker": true,
754
768
  "lowLatencyMode": true,
@@ -35,14 +35,14 @@ const LadderTemplate = {
35
35
  stream_name: "video",
36
36
  width: 960
37
37
  },
38
- "360": {
39
- bit_rate: 520000,
38
+ "540_low": {
39
+ bit_rate: 900000,
40
40
  codecs: "avc1.640028,mp4a.40.2",
41
- height: 360,
41
+ height: 540,
42
42
  media_type: 1,
43
- representation: "videovideo_640x360_h264@520000",
43
+ representation: "videovideo_960x540_h264@900000",
44
44
  stream_name: "video",
45
- width: 640
45
+ width: 960
46
46
  }
47
47
  };
48
48
 
@@ -236,9 +236,9 @@ class LiveConf {
236
236
  return sync_id;
237
237
  }
238
238
 
239
- generateLiveConf() {
239
+ generateLiveConf({audioBitrate, audioIndex, partTtl, channelLayout}) {
240
240
  // gather required data
241
- const conf = LiveconfTemplate;
241
+ const conf = JSON.parse(JSON.stringify(LiveconfTemplate));
242
242
  const fileName = this.overwriteOriginUrl || this.probeData.format.filename;
243
243
  const audioStream = this.getStreamDataForCodecType("audio");
244
244
  const sampleRate = parseInt(audioStream.sample_rate);
@@ -255,7 +255,7 @@ class LiveConf {
255
255
  conf.live_recording.recording_config.recording_params.origin_url = fileName;
256
256
  conf.live_recording.recording_config.recording_params.description = `Ingest stream ${fileName}`;
257
257
  conf.live_recording.recording_config.recording_params.name = `Ingest stream ${fileName}`;
258
- conf.live_recording.recording_config.recording_params.xc_params.audio_index[0] = audioStream.stream_index;
258
+ conf.live_recording.recording_config.recording_params.xc_params.audio_index[0] = audioIndex === undefined ? audioStream.stream_index : audioIndex;
259
259
  conf.live_recording.recording_config.recording_params.xc_params.sample_rate = sampleRate;
260
260
  conf.live_recording.recording_config.recording_params.xc_params.enc_height = videoStream.height;
261
261
  conf.live_recording.recording_config.recording_params.xc_params.enc_width = videoStream.width;
@@ -264,6 +264,10 @@ class LiveConf {
264
264
  conf.live_recording.recording_config.recording_params.xc_params.sync_audio_to_stream_id = this.syncAudioToStreamIdValue();
265
265
  }
266
266
 
267
+ if(partTtl) {
268
+ conf.live_recording.recording_config.recording_params.part_ttl = partTtl;
269
+ }
270
+
267
271
  // Fill in specifics for protocol
268
272
  switch(this.probeKind()) {
269
273
  case "udp":
@@ -297,7 +301,7 @@ class LiveConf {
297
301
  LadderTemplate[1080],
298
302
  LadderTemplate[720],
299
303
  LadderTemplate[540],
300
- LadderTemplate[360]
304
+ LadderTemplate["540_low"]
301
305
  );
302
306
  conf.live_recording.recording_config.recording_params.xc_params.video_bitrate = LadderTemplate[2160].bit_rate;
303
307
  conf.live_recording.recording_config.recording_params.xc_params.enc_height = 2160;
@@ -309,7 +313,7 @@ class LiveConf {
309
313
  LadderTemplate[1080],
310
314
  LadderTemplate[720],
311
315
  LadderTemplate[540],
312
- LadderTemplate[360]
316
+ LadderTemplate["540_low"]
313
317
  );
314
318
  conf.live_recording.recording_config.recording_params.xc_params.video_bitrate = LadderTemplate[1080].bit_rate;
315
319
  conf.live_recording.recording_config.recording_params.xc_params.enc_height = 1080;
@@ -319,7 +323,7 @@ class LiveConf {
319
323
  conf.live_recording.recording_config.recording_params.ladder_specs.unshift(
320
324
  LadderTemplate[720],
321
325
  LadderTemplate[540],
322
- LadderTemplate[360]
326
+ LadderTemplate["540_low"]
323
327
  );
324
328
  conf.live_recording.recording_config.recording_params.xc_params.video_bitrate = LadderTemplate[720].bit_rate;
325
329
  conf.live_recording.recording_config.recording_params.xc_params.enc_height = 720;
@@ -328,21 +332,28 @@ class LiveConf {
328
332
  case 540:
329
333
  conf.live_recording.recording_config.recording_params.ladder_specs.unshift(
330
334
  LadderTemplate[540],
331
- LadderTemplate[360]
335
+ LadderTemplate["540_low"]
332
336
  );
333
337
  conf.live_recording.recording_config.recording_params.xc_params.video_bitrate = LadderTemplate[540].bit_rate;
334
338
  conf.live_recording.recording_config.recording_params.xc_params.enc_height = 540;
335
339
  conf.live_recording.recording_config.recording_params.xc_params.enc_width = 960;
336
340
  break;
337
- case 360:
338
- conf.live_recording.recording_config.recording_params.ladder_specs.unshift(LadderTemplate[360]);
339
- conf.live_recording.recording_config.recording_params.ladder_specs.unshift(LadderTemplate[360]);
340
- conf.live_recording.recording_config.recording_params.xc_params.video_bitrate = LadderTemplate[360].bit_rate;
341
- conf.live_recording.recording_config.recording_params.xc_params.enc_height = 360;
342
- conf.live_recording.recording_config.recording_params.xc_params.enc_width = 640;
343
- break;
344
341
  default:
345
- throw new Error("ERROR: Probed stream does not conform to one of the following built in resolution ladders [4096, 2160], [1920, 1080] [1280, 720], [960, 540], [640, 360]");
342
+ throw new Error("ERROR: Probed stream does not conform to one of the following built in resolution ladders [4096, 2160], [1920, 1080] [1280, 720], [960, 540]");
343
+ }
344
+
345
+ if(audioBitrate || channelLayout) {
346
+ const audioLadderSpec = conf.live_recording.recording_config.recording_params.ladder_specs.find(spec => spec.stream_name === "audio");
347
+
348
+ if(audioBitrate) {
349
+ conf.live_recording.recording_config.recording_params.xc_params.audio_bitrate = audioBitrate;
350
+ audioLadderSpec.bit_rate = audioBitrate;
351
+ audioLadderSpec.representation = `audioaudio_aac@${audioBitrate}`;
352
+ }
353
+
354
+ if(channelLayout) {
355
+ audioLadderSpec.channels = channelLayout;
356
+ }
346
357
  }
347
358
 
348
359
  return JSON.stringify(conf, null, 2);
@@ -1118,7 +1118,7 @@ exports.LoadConf = async function({name}) {
1118
1118
  * @return {Object} - The status response for the stream
1119
1119
  *
1120
1120
  */
1121
- exports.StreamConfig = async function({name}) {
1121
+ exports.StreamConfig = async function({name, customSettings}) {
1122
1122
  let conf = await this.LoadConf({name});
1123
1123
  let status = {name};
1124
1124
 
@@ -1191,10 +1191,15 @@ exports.StreamConfig = async function({name}) {
1191
1191
  console.log("PROBE", probe);
1192
1192
  probe.format.filename = streamUrl.href;
1193
1193
 
1194
- // Create live reocording config
1194
+ // Create live recording config
1195
1195
  let lc = new LiveConf(probe, node.id, endpoint, false, false, true);
1196
1196
 
1197
- const liveRecordingConfigStr = lc.generateLiveConf();
1197
+ const liveRecordingConfigStr = lc.generateLiveConf({
1198
+ audioBitrate: customSettings.audioBitrate,
1199
+ audioIndex: customSettings.audioIndex,
1200
+ partTtl: customSettings.partTtl,
1201
+ channelLayout: customSettings.channelLayout
1202
+ });
1198
1203
  let liveRecordingConfig = JSON.parse(liveRecordingConfigStr);
1199
1204
  console.log("CONFIG", JSON.stringify(liveRecordingConfig.live_recording));
1200
1205
 
@@ -1213,6 +1218,14 @@ exports.StreamConfig = async function({name}) {
1213
1218
  metadata: liveRecordingConfig.live_recording
1214
1219
  });
1215
1220
 
1221
+ await this.ReplaceMetadata({
1222
+ libraryId,
1223
+ objectId: conf.objectId,
1224
+ writeToken,
1225
+ metadataSubtree: "probe",
1226
+ metadata: probe
1227
+ });
1228
+
1216
1229
  status.fin = await this.FinalizeContentObject({
1217
1230
  libraryId,
1218
1231
  objectId: conf.objectId,
@@ -13,17 +13,18 @@ const NotificationPath = ({network, path}) => {
13
13
  };
14
14
 
15
15
  /**
16
- * Push a notification to the current user
16
+ * Push a notification to a user
17
17
  *
18
18
  * @methodGroup Notifications
19
19
  * @param {string} tenantId - The tenant associated with this notification
20
20
  * @param {string} eventType - The type of the notification
21
21
  * @param {(Object | string)=} data - Data associated with this notification
22
+ * @param {string=} userAddress - Address of the user to notify. If not specified, it will be sent to the current user.
22
23
  */
23
- exports.PushNotification = async function({tenantId, eventType, data}) {
24
+ exports.PushNotification = async function({tenantId, eventType, data, userAddress}) {
24
25
  await this.stateStoreClient.Request({
25
26
  method: "POST",
26
- path: NotificationPath({network: this.network, path: UrlJoin("notify_user", this.UserAddress(), tenantId, eventType)}),
27
+ path: NotificationPath({network: this.network, path: UrlJoin("notify_user", userAddress || this.UserAddress(), tenantId, eventType)}),
27
28
  body: data,
28
29
  headers: {
29
30
  Authorization: `Bearer ${this.AuthToken()}`