@micromag/element-video 0.3.579 → 0.3.582

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 +101 -34
  2. package/package.json +2 -2
package/es/index.js CHANGED
@@ -2,6 +2,7 @@ import _defineProperty from '@babel/runtime/helpers/defineProperty';
2
2
  import _objectSpread from '@babel/runtime/helpers/objectSpread2';
3
3
  import _slicedToArray from '@babel/runtime/helpers/slicedToArray';
4
4
  import classNames from 'classnames';
5
+ import Hls from 'hls.js';
5
6
  import isFunction from 'lodash/isFunction';
6
7
  import PropTypes$1 from 'prop-types';
7
8
  import React, { useMemo, useRef, useState, useEffect, useCallback } from 'react';
@@ -9,7 +10,6 @@ import { PropTypes } from '@micromag/core';
9
10
  import { Spinner } from '@micromag/core/components';
10
11
  import { useMediaThumbnail, useMediaCurrentTime, useMediaDuration, useMediaReady, useProgressSteps } from '@micromag/core/hooks';
11
12
  import { getMediaFilesAsArray, getVideoSupportedMimes } from '@micromag/core/utils';
12
- import Hls from 'hls.js';
13
13
 
14
14
  var styles = {"container":"micromag-element-video-container","withSize":"micromag-element-video-withSize","media":"micromag-element-video-media","spinner":"micromag-element-video-spinner"};
15
15
 
@@ -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 _ref12 = useRef(null);
138
- var currentTime = useMediaCurrentTime(_ref12.current, {
143
+ var _ref15 = useRef(null);
144
+ var currentTime = useMediaCurrentTime(_ref15.current, {
139
145
  id: mediaUrl,
140
146
  disabled: paused || onProgressStep === null
141
147
  });
142
- var duration = useMediaDuration(_ref12.current, {
148
+ var duration = useMediaDuration(_ref15.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(_ref12.current, {
155
+ var ready = useMediaReady(_ref15.current, {
150
156
  id: mediaUrl
151
157
  });
152
158
  useEffect(function () {
@@ -176,16 +182,75 @@ var Video = function Video(_ref) {
176
182
  return mime === 'application/vnd.apple.mpegurl' || (name || '').endsWith('.m3u8');
177
183
  });
178
184
  }, [filesArray, hlsIsSupported, disableHls]);
185
+ var _useState3 = useState(null),
186
+ _useState4 = _slicedToArray(_useState3, 2),
187
+ hlsJs = _useState4[0],
188
+ setHlsJs = _useState4[1];
189
+ var _useState5 = useState(0),
190
+ _useState6 = _slicedToArray(_useState5, 2),
191
+ hlsTsOffset = _useState6[0],
192
+ setHlsTsOffset = _useState6[1];
193
+
194
+ // initialize hls instance if an hls source is provided
179
195
  useEffect(function () {
180
- if (_ref12.current === null || !hlsIsSupported) {
196
+ if (_ref15.current === null || !hlsIsSupported) {
181
197
  return;
182
198
  }
183
- if (hlsSources !== null && hlsSources.length > 0) {
184
- var hls = new Hls();
199
+ setHlsTsOffset(0);
200
+ if (shouldLoad && hlsSources !== null && hlsSources.length > 0) {
201
+ var hls = new Hls({
202
+ startLevel: qualityStartLevel
203
+ });
204
+ hls.on(Hls.Events.LEVEL_SWITCHED, function (_, _ref5) {
205
+ var level = _ref5.level;
206
+ if (onQualityLevelChange !== null) {
207
+ onQualityLevelChange(level);
208
+ }
209
+ });
210
+
211
+ // compute hls timestamp offset when we get the first video fragment
212
+ var _onHlsBufferAppended = function onHlsBufferAppended(_, _ref6) {
213
+ var frag = _ref6.frag;
214
+ var fragStart = frag.start,
215
+ fragType = frag.type,
216
+ _frag$sn = frag.sn,
217
+ fragSn = _frag$sn === void 0 ? null : _frag$sn,
218
+ _frag$elementaryStrea = frag.elementaryStreams.video,
219
+ videoStream = _frag$elementaryStrea === void 0 ? null : _frag$elementaryStrea;
220
+ var _ref7 = videoStream || {},
221
+ _ref7$startPTS = _ref7.startPTS,
222
+ videoStartPTS = _ref7$startPTS === void 0 ? null : _ref7$startPTS;
223
+ if (fragType === 'main' && fragSn !== 'initSegment' && videoStartPTS !== null) {
224
+ var tOffset = videoStartPTS - fragStart;
225
+ hls.off(Hls.Events.BUFFER_APPENDED, _onHlsBufferAppended);
226
+ setHlsTsOffset(tOffset);
227
+ }
228
+ };
229
+ hls.on(Hls.Events.BUFFER_APPENDED, _onHlsBufferAppended);
185
230
  hls.loadSource(hlsSources[0].url);
186
- hls.attachMedia(_ref12.current);
231
+ setHlsJs(hls);
187
232
  }
188
- }, [hlsIsSupported, hlsSources, _ref12]);
233
+ }, [shouldLoad, hlsIsSupported, hlsSources, _ref15]);
234
+
235
+ // attach hls.js when the <video> ref is ready
236
+ useEffect(function () {
237
+ if (hlsJs !== null && _ref15.current !== null) {
238
+ hlsJs.attachMedia(_ref15.current);
239
+ }
240
+ return function () {
241
+ if (hlsJs !== null) {
242
+ hlsJs.detachMedia();
243
+ hlsJs.destroy();
244
+ }
245
+ };
246
+ }, [hlsJs, _ref15.current]);
247
+
248
+ // handle changes of qualityStartLevel when an hls.js instance exists
249
+ useEffect(function () {
250
+ if (hlsJs !== null) {
251
+ hlsJs.startLevel = qualityStartLevel;
252
+ }
253
+ }, [qualityStartLevel]);
189
254
  var sourceFiles = useMemo(function () {
190
255
  if (filesArray.length === 0 || hlsSources !== null && hlsSources.length > 0) {
191
256
  return null;
@@ -204,11 +269,11 @@ var Video = function Video(_ref) {
204
269
  var _file$mime2 = file.mime,
205
270
  mime = _file$mime2 === void 0 ? "video/".concat(fileHandle === 'h264' ? 'mp4' : fileHandle) : _file$mime2;
206
271
  var currentMimeFile = filesMap[mime] || null;
207
- var _ref5 = currentMimeFile || {},
208
- _ref5$id = _ref5.id,
209
- currentId = _ref5$id === void 0 ? null : _ref5$id,
210
- _ref5$handle = _ref5.handle,
211
- currentHandle = _ref5$handle === void 0 ? null : _ref5$handle;
272
+ var _ref8 = currentMimeFile || {},
273
+ _ref8$id = _ref8.id,
274
+ currentId = _ref8$id === void 0 ? null : _ref8$id,
275
+ _ref8$handle = _ref8.handle,
276
+ currentHandle = _ref8$handle === void 0 ? null : _ref8$handle;
212
277
  var currentMimeHandle = currentHandle || currentId;
213
278
  return currentMimeFile === null || currentMimeHandle === 'original' ? _objectSpread(_objectSpread({}, filesMap), {}, _defineProperty({}, mime, file)) : filesMap;
214
279
  }, {});
@@ -218,14 +283,14 @@ var Video = function Video(_ref) {
218
283
  }, [filesArray, hlsSources]);
219
284
 
220
285
  // @NOTE: Media is an animated image and doesn't have source files in video formats
221
- var _ref6 = filesArray.find(function (_ref7) {
222
- var handle = _ref7.handle;
286
+ var _ref9 = filesArray.find(function (_ref10) {
287
+ var handle = _ref10.handle;
223
288
  return handle === 'original';
224
289
  }) || {},
225
- _ref6$type = _ref6.type,
226
- originalType = _ref6$type === void 0 ? null : _ref6$type,
227
- _ref6$mime = _ref6.mime,
228
- originalMime = _ref6$mime === void 0 ? mediaMime : _ref6$mime;
290
+ _ref9$type = _ref9.type,
291
+ originalType = _ref9$type === void 0 ? null : _ref9$type,
292
+ _ref9$mime = _ref9.mime,
293
+ originalMime = _ref9$mime === void 0 ? mediaMime : _ref9$mime;
229
294
  var originalFileIsImage = originalType === 'image' || originalMime !== null && originalMime.indexOf('image/') === 0;
230
295
  var isImageWithoutSourceFile = originalFileIsImage && (sourceFiles === null || sourceFiles.length === 0);
231
296
  var withSize = width !== null && height !== null;
@@ -235,7 +300,7 @@ var Video = function Video(_ref) {
235
300
  }
236
301
  }, [duration, customOnDurationChange]);
237
302
  var onVolumeChange = useCallback(function () {
238
- var _ref$current = _ref12.current,
303
+ var _ref$current = _ref15.current,
239
304
  element = _ref$current === void 0 ? null : _ref$current;
240
305
  if (element === null) {
241
306
  return;
@@ -246,10 +311,10 @@ var Video = function Video(_ref) {
246
311
  }, [customOnVolumeChange]);
247
312
 
248
313
  // Manage suspend
249
- var _useState3 = useState(false),
250
- _useState4 = _slicedToArray(_useState3, 2),
251
- isSuspended = _useState4[0],
252
- setIsSuspended = _useState4[1];
314
+ var _useState7 = useState(false),
315
+ _useState8 = _slicedToArray(_useState7, 2),
316
+ isSuspended = _useState8[0],
317
+ setIsSuspended = _useState8[1];
253
318
  var onPlay = useCallback(function (e) {
254
319
  if (isSuspended) {
255
320
  setIsSuspended(false);
@@ -280,7 +345,7 @@ var Video = function Video(_ref) {
280
345
  }
281
346
  }, [ready, onReady]);
282
347
  useEffect(function () {
283
- var _ref$current2 = _ref12.current,
348
+ var _ref$current2 = _ref15.current,
284
349
  element = _ref$current2 === void 0 ? null : _ref$current2;
285
350
  if (element === null) {
286
351
  return;
@@ -317,7 +382,7 @@ var Video = function Video(_ref) {
317
382
  }) : null, !isImageWithoutSourceFile ? /*#__PURE__*/React.createElement("video", {
318
383
  key: mediaUrl,
319
384
  ref: function ref(newRef) {
320
- _ref12.current = newRef;
385
+ _ref15.current = newRef;
321
386
  if (mediaRef !== null && isFunction(mediaRef)) {
322
387
  mediaRef(newRef);
323
388
  } else if (mediaRef !== null) {
@@ -345,10 +410,12 @@ var Video = function Video(_ref) {
345
410
  onSuspend: onSuspend,
346
411
  "data-has-audio": hasAudio,
347
412
  "data-is-suspended": isSuspended,
413
+ "data-hls": hlsJs !== null,
414
+ "data-ts-offset": hlsTsOffset,
348
415
  "aria-hidden": true
349
- }, (sourceFiles || []).map(function (_ref11) {
350
- var sourceUrl = _ref11.url,
351
- sourceMime = _ref11.mime;
416
+ }, (sourceFiles || []).map(function (_ref14) {
417
+ var sourceUrl = _ref14.url,
418
+ sourceMime = _ref14.mime;
352
419
  return /*#__PURE__*/React.createElement("source", {
353
420
  key: "".concat(sourceUrl, "-").concat(sourceMime),
354
421
  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.579",
3
+ "version": "0.3.582",
4
4
  "private": false,
5
5
  "description": "",
6
6
  "keywords": [
@@ -72,5 +72,5 @@
72
72
  "access": "public",
73
73
  "registry": "https://registry.npmjs.org/"
74
74
  },
75
- "gitHead": "4c435acd50f36704c12652d8df9e5a86cfe0cf08"
75
+ "gitHead": "95704cba6bce8f9329171fbcb06acba2543decc0"
76
76
  }