@micromag/element-video 0.3.580 → 0.3.583

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/es/index.js +113 -64
  2. package/package.json +4 -4
package/es/index.js CHANGED
@@ -45,9 +45,11 @@ var propTypes = {
45
45
  onSuspend: PropTypes$1.func,
46
46
  onSuspended: PropTypes$1.func,
47
47
  onPlayError: PropTypes$1.func,
48
+ onQualityLevelChange: PropTypes$1.func,
48
49
  focusable: PropTypes$1.bool,
49
50
  withPoster: PropTypes$1.bool,
50
- withLoading: PropTypes$1.bool
51
+ withLoading: PropTypes$1.bool,
52
+ qualityStartLevel: PropTypes$1.number
51
53
  };
52
54
  var defaultProps = {
53
55
  media: null,
@@ -79,9 +81,11 @@ var defaultProps = {
79
81
  onSuspend: null,
80
82
  onSuspended: null,
81
83
  onPlayError: null,
84
+ onQualityLevelChange: null,
82
85
  focusable: true,
83
86
  withPoster: false,
84
- withLoading: false
87
+ withLoading: false,
88
+ qualityStartLevel: -1
85
89
  };
86
90
  var Video = function Video(_ref) {
87
91
  var media = _ref.media,
@@ -111,11 +115,13 @@ var Video = function Video(_ref) {
111
115
  customOnSuspend = _ref.onSuspend,
112
116
  onSuspended = _ref.onSuspended,
113
117
  onPlayError = _ref.onPlayError,
118
+ onQualityLevelChange = _ref.onQualityLevelChange,
114
119
  focusable = _ref.focusable,
115
120
  withPoster = _ref.withPoster,
116
121
  withLoading = _ref.withLoading,
117
122
  disablePictureInPicture = _ref.disablePictureInPicture,
118
- disableHls = _ref.disableHls;
123
+ disableHls = _ref.disableHls,
124
+ qualityStartLevel = _ref.qualityStartLevel;
119
125
  var _ref2 = media || {},
120
126
  _ref2$url = _ref2.url,
121
127
  mediaUrl = _ref2$url === void 0 ? null : _ref2$url,
@@ -134,19 +140,19 @@ var Video = function Video(_ref) {
134
140
  return getMediaFilesAsArray(files);
135
141
  }, [files]);
136
142
  var finalThumbnail = useMediaThumbnail(media, thumbnail);
137
- var _ref14 = useRef(null);
138
- var currentTime = useMediaCurrentTime(_ref14.current, {
143
+ var _ref16 = useRef(null);
144
+ var currentTime = useMediaCurrentTime(_ref16.current, {
139
145
  id: mediaUrl,
140
146
  disabled: paused || onProgressStep === null
141
147
  });
142
- var duration = useMediaDuration(_ref14.current, {
148
+ var duration = useMediaDuration(_ref16.current, {
143
149
  id: mediaUrl
144
150
  });
145
151
  var _useState = useState(false),
146
152
  _useState2 = _slicedToArray(_useState, 2),
147
153
  showLoading = _useState2[0],
148
154
  setShowLoading = _useState2[1];
149
- var ready = useMediaReady(_ref14.current, {
155
+ var ready = useMediaReady(_ref16.current, {
150
156
  id: mediaUrl
151
157
  });
152
158
  useEffect(function () {
@@ -161,11 +167,12 @@ var Video = function Video(_ref) {
161
167
  clearTimeout(id);
162
168
  };
163
169
  }, [mediaUrl, withLoading]);
164
- var hlsIsSupported = useMemo(function () {
165
- return Hls.isSupported();
166
- }, [Hls]);
170
+ var _useState3 = useState(false),
171
+ _useState4 = _slicedToArray(_useState3, 2),
172
+ hlsFailed = _useState4[0],
173
+ setHlsFailed = _useState4[1];
167
174
  var hlsSources = useMemo(function () {
168
- if (filesArray.length === 0 || disableHls) {
175
+ if (filesArray.length === 0 || disableHls || !Hls.isSupported() || hlsFailed) {
169
176
  return null;
170
177
  }
171
178
  return filesArray.filter(function (_ref4) {
@@ -175,44 +182,62 @@ var Video = function Video(_ref) {
175
182
  name = _ref4$name === void 0 ? null : _ref4$name;
176
183
  return mime === 'application/vnd.apple.mpegurl' || (name || '').endsWith('.m3u8');
177
184
  });
178
- }, [filesArray, hlsIsSupported, disableHls]);
179
- var _useState3 = useState(null),
180
- _useState4 = _slicedToArray(_useState3, 2),
181
- hlsJs = _useState4[0],
182
- setHlsJs = _useState4[1];
183
- useEffect(function () {
184
- if (hlsJs !== null && _ref14.current !== null) {
185
- hlsJs.attachMedia(_ref14.current);
186
- }
187
- return function () {
188
- if (hlsJs !== null) {
189
- hlsJs.detachMedia();
190
- hlsJs.destroy();
191
- }
192
- };
193
- }, [hlsJs, _ref14.current]);
194
- var _useState5 = useState(0),
195
- _useState6 = _slicedToArray(_useState5, 2);
196
- _useState6[0];
197
- var setHlsTsOffset = _useState6[1];
185
+ }, [filesArray, disableHls, hlsFailed]);
186
+ var _useState5 = useState(null),
187
+ _useState6 = _slicedToArray(_useState5, 2),
188
+ hlsJs = _useState6[0],
189
+ setHlsJs = _useState6[1];
190
+ var _useState7 = useState(0),
191
+ _useState8 = _slicedToArray(_useState7, 2),
192
+ hlsTsOffset = _useState8[0],
193
+ setHlsTsOffset = _useState8[1];
194
+
195
+ // initialize hls instance if an hls source is provided
198
196
  useEffect(function () {
199
- if (_ref14.current === null || !hlsIsSupported) {
200
- return;
201
- }
202
- if (hlsSources !== null && hlsSources.length > 0) {
203
- setHlsTsOffset(0);
204
- var hls = new Hls();
205
- var _onHlsBufferAppended = function onHlsBufferAppended(eventName, _ref5) {
206
- var frag = _ref5.frag;
197
+ setHlsTsOffset(0);
198
+ setHlsFailed(false);
199
+ if (shouldLoad && _ref16.current !== null && hlsSources !== null && hlsSources.length > 0) {
200
+ var hls = new Hls({
201
+ maxBufferLength: 15,
202
+ // seconds. prevents loading too much per screen.
203
+ startLevel: qualityStartLevel
204
+ });
205
+ hls.on(Hls.Events.LEVEL_SWITCHED, function (_, _ref5) {
206
+ var level = _ref5.level;
207
+ if (onQualityLevelChange !== null) {
208
+ onQualityLevelChange(level);
209
+ }
210
+ });
211
+ hls.on(Hls.Events.ERROR, function (_, _ref6) {
212
+ var isFatal = _ref6.fatal,
213
+ errorType = _ref6.type;
214
+ if (isFatal) {
215
+ switch (errorType) {
216
+ case Hls.ErrorTypes.MEDIA_ERROR:
217
+ // automatically try to recover from media errors
218
+ hls.recoverMediaError();
219
+ break;
220
+ case Hls.ErrorTypes.NETWORK_ERROR:
221
+ // happens when all retries and media options have been exhausted. in that case, fallback to mp4/webm playback
222
+ setHlsJs(null);
223
+ setHlsFailed(true);
224
+ break;
225
+ }
226
+ }
227
+ });
228
+
229
+ // compute hls timestamp offset when we get the first video fragment
230
+ var _onHlsBufferAppended = function onHlsBufferAppended(_, _ref7) {
231
+ var frag = _ref7.frag;
207
232
  var fragStart = frag.start,
208
233
  fragType = frag.type,
209
234
  _frag$sn = frag.sn,
210
235
  fragSn = _frag$sn === void 0 ? null : _frag$sn,
211
236
  _frag$elementaryStrea = frag.elementaryStreams.video,
212
237
  videoStream = _frag$elementaryStrea === void 0 ? null : _frag$elementaryStrea;
213
- var _ref6 = videoStream || {},
214
- _ref6$startPTS = _ref6.startPTS,
215
- videoStartPTS = _ref6$startPTS === void 0 ? null : _ref6$startPTS;
238
+ var _ref8 = videoStream || {},
239
+ _ref8$startPTS = _ref8.startPTS,
240
+ videoStartPTS = _ref8$startPTS === void 0 ? null : _ref8$startPTS;
216
241
  if (fragType === 'main' && fragSn !== 'initSegment' && videoStartPTS !== null) {
217
242
  var tOffset = videoStartPTS - fragStart;
218
243
  hls.off(Hls.Events.BUFFER_APPENDED, _onHlsBufferAppended);
@@ -222,8 +247,30 @@ var Video = function Video(_ref) {
222
247
  hls.on(Hls.Events.BUFFER_APPENDED, _onHlsBufferAppended);
223
248
  hls.loadSource(hlsSources[0].url);
224
249
  setHlsJs(hls);
250
+ } else {
251
+ setHlsJs(null);
252
+ }
253
+ }, [shouldLoad, hlsSources, _ref16]);
254
+
255
+ // attach hls.js when the <video> ref is ready
256
+ useEffect(function () {
257
+ if (hlsJs !== null && _ref16.current !== null) {
258
+ hlsJs.attachMedia(_ref16.current);
259
+ }
260
+ return function () {
261
+ if (hlsJs !== null) {
262
+ hlsJs.detachMedia();
263
+ hlsJs.destroy();
264
+ }
265
+ };
266
+ }, [hlsJs, _ref16.current]);
267
+
268
+ // handle changes of qualityStartLevel when an hls.js instance exists
269
+ useEffect(function () {
270
+ if (hlsJs !== null) {
271
+ hlsJs.startLevel = qualityStartLevel;
225
272
  }
226
- }, [hlsIsSupported, hlsSources, _ref14]);
273
+ }, [qualityStartLevel]);
227
274
  var sourceFiles = useMemo(function () {
228
275
  if (filesArray.length === 0 || hlsSources !== null && hlsSources.length > 0) {
229
276
  return null;
@@ -242,11 +289,11 @@ var Video = function Video(_ref) {
242
289
  var _file$mime2 = file.mime,
243
290
  mime = _file$mime2 === void 0 ? "video/".concat(fileHandle === 'h264' ? 'mp4' : fileHandle) : _file$mime2;
244
291
  var currentMimeFile = filesMap[mime] || null;
245
- var _ref7 = currentMimeFile || {},
246
- _ref7$id = _ref7.id,
247
- currentId = _ref7$id === void 0 ? null : _ref7$id,
248
- _ref7$handle = _ref7.handle,
249
- currentHandle = _ref7$handle === void 0 ? null : _ref7$handle;
292
+ var _ref9 = currentMimeFile || {},
293
+ _ref9$id = _ref9.id,
294
+ currentId = _ref9$id === void 0 ? null : _ref9$id,
295
+ _ref9$handle = _ref9.handle,
296
+ currentHandle = _ref9$handle === void 0 ? null : _ref9$handle;
250
297
  var currentMimeHandle = currentHandle || currentId;
251
298
  return currentMimeFile === null || currentMimeHandle === 'original' ? _objectSpread(_objectSpread({}, filesMap), {}, _defineProperty({}, mime, file)) : filesMap;
252
299
  }, {});
@@ -256,14 +303,14 @@ var Video = function Video(_ref) {
256
303
  }, [filesArray, hlsSources]);
257
304
 
258
305
  // @NOTE: Media is an animated image and doesn't have source files in video formats
259
- var _ref8 = filesArray.find(function (_ref9) {
260
- var handle = _ref9.handle;
306
+ var _ref10 = filesArray.find(function (_ref11) {
307
+ var handle = _ref11.handle;
261
308
  return handle === 'original';
262
309
  }) || {},
263
- _ref8$type = _ref8.type,
264
- originalType = _ref8$type === void 0 ? null : _ref8$type,
265
- _ref8$mime = _ref8.mime,
266
- originalMime = _ref8$mime === void 0 ? mediaMime : _ref8$mime;
310
+ _ref10$type = _ref10.type,
311
+ originalType = _ref10$type === void 0 ? null : _ref10$type,
312
+ _ref10$mime = _ref10.mime,
313
+ originalMime = _ref10$mime === void 0 ? mediaMime : _ref10$mime;
267
314
  var originalFileIsImage = originalType === 'image' || originalMime !== null && originalMime.indexOf('image/') === 0;
268
315
  var isImageWithoutSourceFile = originalFileIsImage && (sourceFiles === null || sourceFiles.length === 0);
269
316
  var withSize = width !== null && height !== null;
@@ -273,7 +320,7 @@ var Video = function Video(_ref) {
273
320
  }
274
321
  }, [duration, customOnDurationChange]);
275
322
  var onVolumeChange = useCallback(function () {
276
- var _ref$current = _ref14.current,
323
+ var _ref$current = _ref16.current,
277
324
  element = _ref$current === void 0 ? null : _ref$current;
278
325
  if (element === null) {
279
326
  return;
@@ -284,10 +331,10 @@ var Video = function Video(_ref) {
284
331
  }, [customOnVolumeChange]);
285
332
 
286
333
  // Manage suspend
287
- var _useState7 = useState(false),
288
- _useState8 = _slicedToArray(_useState7, 2),
289
- isSuspended = _useState8[0],
290
- setIsSuspended = _useState8[1];
334
+ var _useState9 = useState(false),
335
+ _useState10 = _slicedToArray(_useState9, 2),
336
+ isSuspended = _useState10[0],
337
+ setIsSuspended = _useState10[1];
291
338
  var onPlay = useCallback(function (e) {
292
339
  if (isSuspended) {
293
340
  setIsSuspended(false);
@@ -318,7 +365,7 @@ var Video = function Video(_ref) {
318
365
  }
319
366
  }, [ready, onReady]);
320
367
  useEffect(function () {
321
- var _ref$current2 = _ref14.current,
368
+ var _ref$current2 = _ref16.current,
322
369
  element = _ref$current2 === void 0 ? null : _ref$current2;
323
370
  if (element === null) {
324
371
  return;
@@ -355,7 +402,7 @@ var Video = function Video(_ref) {
355
402
  }) : null, !isImageWithoutSourceFile ? /*#__PURE__*/React.createElement("video", {
356
403
  key: mediaUrl,
357
404
  ref: function ref(newRef) {
358
- _ref14.current = newRef;
405
+ _ref16.current = newRef;
359
406
  if (mediaRef !== null && isFunction(mediaRef)) {
360
407
  mediaRef(newRef);
361
408
  } else if (mediaRef !== null) {
@@ -383,10 +430,12 @@ var Video = function Video(_ref) {
383
430
  onSuspend: onSuspend,
384
431
  "data-has-audio": hasAudio,
385
432
  "data-is-suspended": isSuspended,
433
+ "data-hls": hlsJs !== null,
434
+ "data-ts-offset": hlsTsOffset,
386
435
  "aria-hidden": true
387
- }, (sourceFiles || []).map(function (_ref13) {
388
- var sourceUrl = _ref13.url,
389
- sourceMime = _ref13.mime;
436
+ }, (sourceFiles || []).map(function (_ref15) {
437
+ var sourceUrl = _ref15.url,
438
+ sourceMime = _ref15.mime;
390
439
  return /*#__PURE__*/React.createElement("source", {
391
440
  key: "".concat(sourceUrl, "-").concat(sourceMime),
392
441
  src: sourceUrl !== null ? "".concat(sourceUrl, "#t=0.001") : null,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@micromag/element-video",
3
- "version": "0.3.580",
3
+ "version": "0.3.583",
4
4
  "private": false,
5
5
  "description": "",
6
6
  "keywords": [
@@ -59,8 +59,8 @@
59
59
  },
60
60
  "dependencies": {
61
61
  "@babel/runtime": "^7.13.10",
62
- "@micromag/core": "^0.3.578",
63
- "@micromag/element-closed-captions": "^0.3.578",
62
+ "@micromag/core": "^0.3.583",
63
+ "@micromag/element-closed-captions": "^0.3.583",
64
64
  "classnames": "^2.2.6",
65
65
  "hls.js": "^1.5.15",
66
66
  "lodash": "^4.17.21",
@@ -72,5 +72,5 @@
72
72
  "access": "public",
73
73
  "registry": "https://registry.npmjs.org/"
74
74
  },
75
- "gitHead": "8534b331c1ddf17be6cb2bb33dc32f6ed31cf391"
75
+ "gitHead": "d899cc28ac1f5b552114d8bfcd668a9bb8ab651c"
76
76
  }