UNPKG

@lahzenegar/video-react

Version:

Video-React is a web video player built from the ground up for an HTML5 world using React library.

1,664 lines (1,402 loc) 47.8 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _extends2 = require('babel-runtime/helpers/extends'); var _extends3 = _interopRequireDefault(_extends2); var _regenerator = require('babel-runtime/regenerator'); var _regenerator2 = _interopRequireDefault(_regenerator); var _asyncToGenerator2 = require('babel-runtime/helpers/asyncToGenerator'); var _asyncToGenerator3 = _interopRequireDefault(_asyncToGenerator2); var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of'); var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); var _createClass2 = require('babel-runtime/helpers/createClass'); var _createClass3 = _interopRequireDefault(_createClass2); var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn'); var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); var _inherits2 = require('babel-runtime/helpers/inherits'); var _inherits3 = _interopRequireDefault(_inherits2); var _propTypes = require('prop-types'); var _propTypes2 = _interopRequireDefault(_propTypes); var _react = require('react'); var _react2 = _interopRequireDefault(_react); var _classnames = require('classnames'); var _classnames2 = _interopRequireDefault(_classnames); var _vastParser = require('../vast-parser'); var _HLSSource = require('./hls/HLSSource'); var _HLSSource2 = _interopRequireDefault(_HLSSource); var _browser = require('../utils/browser'); var browser = _interopRequireWildcard(_browser); var _utils = require('../utils'); var _AdControllers = require('./AdControllers'); var _AdControllers2 = _interopRequireDefault(_AdControllers); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } var propTypes = { actions: _propTypes2.default.object, player: _propTypes2.default.object, children: _propTypes2.default.any, startTime: _propTypes2.default.number, loop: _propTypes2.default.bool, muted: _propTypes2.default.bool, autoPlay: _propTypes2.default.bool, forceAutoPlay: _propTypes2.default.bool, targetTotalTime: _propTypes2.default.number, playsInline: _propTypes2.default.bool, src: _propTypes2.default.string, poster: _propTypes2.default.string, className: _propTypes2.default.string, preload: _propTypes2.default.oneOf(['auto', 'metadata', 'none']), crossOrigin: _propTypes2.default.string, onLoadStart: _propTypes2.default.func, onWaiting: _propTypes2.default.func, onCanPlay: _propTypes2.default.func, onCanPlayThrough: _propTypes2.default.func, onPlaying: _propTypes2.default.func, onEnded: _propTypes2.default.func, onSeeking: _propTypes2.default.func, onSeeked: _propTypes2.default.func, onPlay: _propTypes2.default.func, onPause: _propTypes2.default.func, onProgress: _propTypes2.default.func, onDurationChange: _propTypes2.default.func, onError: _propTypes2.default.func, onSuspend: _propTypes2.default.func, onAbort: _propTypes2.default.func, onEmptied: _propTypes2.default.func, onStalled: _propTypes2.default.func, onLoadedMetadata: _propTypes2.default.func, onSecondsPlayedReached: _propTypes2.default.func, onLoadedData: _propTypes2.default.func, onTimeUpdate: _propTypes2.default.func, onRateChange: _propTypes2.default.func, onVolumeChange: _propTypes2.default.func, onAllAdsCompleted: _propTypes2.default.func, sendPlayerEvent: _propTypes2.default.func, onAdError: _propTypes2.default.func, onAdStart: _propTypes2.default.func, debugMode: _propTypes2.default.bool, onAdPlaying: _propTypes2.default.func, onStartFirstTime: _propTypes2.default.func, onAdStartFirstTime: _propTypes2.default.func, onVASTLoadedFirstTime: _propTypes2.default.func, onFirstPlayAttempt: _propTypes2.default.func, onFirstPlayAdAttempt: _propTypes2.default.func, onStartError: _propTypes2.default.func, chapters: _propTypes2.default.array, storyboard: _propTypes2.default.object }; var defaultProps = { preload: 'auto' }; var Video = function (_Component) { (0, _inherits3.default)(Video, _Component); function Video(props) { (0, _classCallCheck3.default)(this, Video); var _this = (0, _possibleConstructorReturn3.default)(this, (Video.__proto__ || (0, _getPrototypeOf2.default)(Video)).call(this, props)); _this.isFirstTimeToPlay = true; _this.video = null; _this.isVideoPlayed = false; _this.isReachedSecond = false; _this.delayToStartVideoTimer = null; _this.delayToStartVideoAdTimer = null; _this.videoWaitingTimer = null; _this.defaultAdState = { skipTimeOffset: null, skipOn: null, time: 0, clickThroughUrl: null, isPlaying: false, isPlayed: false, isCompleted: false, source: null, name: null }; _this.totalWaitingDuration = 0; _this.waitingInterval = null; _this.inlinePlay = browser.IS_IOS; _this.state = { ad: _this.defaultAdState, allowToPlay: false, allowToAutoPlay: true, videoURL: null, currentError: null }; _this.metricIntervalTimeout = 10000; _this.play = _this.play.bind(_this); _this.pause = _this.pause.bind(_this); _this.seek = _this.seek.bind(_this); _this.forward = _this.forward.bind(_this); _this.replay = _this.replay.bind(_this); _this.toggleFullscreen = _this.toggleFullscreen.bind(_this); _this.getProperties = _this.getProperties.bind(_this); _this.handleLoadStart = _this.handleLoadStart.bind(_this); _this.handleCanPlay = _this.handleCanPlay.bind(_this); _this.handleCanPlayThrough = _this.handleCanPlayThrough.bind(_this); _this.handlePlay = _this.handlePlay.bind(_this); _this.handlePlaying = _this.handlePlaying.bind(_this); _this.handlePause = _this.handlePause.bind(_this); _this.handleEnded = _this.handleEnded.bind(_this); _this.handleWaiting = _this.handleWaiting.bind(_this); _this.handleSeeking = _this.handleSeeking.bind(_this); _this.handleResize = _this.handleResize.bind(_this); _this.handleSeeked = _this.handleSeeked.bind(_this); _this.handleError = _this.handleError.bind(_this); _this.handleSuspend = _this.handleSuspend.bind(_this); _this.handleAbort = _this.handleAbort.bind(_this); _this.handleEmptied = _this.handleEmptied.bind(_this); _this.handleStalled = _this.handleStalled.bind(_this); _this.handleLoadedMetaData = _this.handleLoadedMetaData.bind(_this); _this.handleLoadedData = _this.handleLoadedData.bind(_this); _this.handleTimeUpdate = _this.handleTimeUpdate.bind(_this); _this.handleRateChange = _this.handleRateChange.bind(_this); _this.handleVolumeChange = _this.handleVolumeChange.bind(_this); _this.handleDurationChange = _this.handleDurationChange.bind(_this); _this.handleProgress = (0, _utils.throttle)(_this.handleProgress.bind(_this), 250); _this.adHandleElapsedTime = _this.adHandleElapsedTime.bind(_this); return _this; } (0, _createClass3.default)(Video, [{ key: 'componentDidMount', value: function () { var _ref = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee() { return _regenerator2.default.wrap(function _callee$(_context) { while (1) { switch (_context.prev = _context.next) { case 0: this.methodCalls('componentDidMount'); window.addEventListener('resize', this.handleResize); _context.next = 4; return this.handleVideoContentInit(); case 4: if (!this.autoPlay) { this.setContentLoading(false); } case 5: case 'end': return _context.stop(); } } }, _callee, this); })); function componentDidMount() { return _ref.apply(this, arguments); } return componentDidMount; }() }, { key: 'componentWillMount', value: function componentWillMount() { this.methodCalls('componentWillMount'); } }, { key: 'componentWillUnmount', value: function componentWillUnmount() { this.methodCalls('componentWillUnmount'); window.removeEventListener('resize', this.handleResize); if (this.delayToStartVideoTimer) { this.delayToStartVideoTimer.end(); } if (this.delayToStartVideoAdTimer) { this.delayToStartVideoAdTimer.end(); } if (this.videoWaitingTimer) { this.videoWaitingTimer.end(); } this.delayToStartVideoTimer = null; this.delayToStartVideoAdTimer = null; this.videoWaitingTimer = null; this.isVideoPlayed = false; this.isReachedSecond = false; this.totalWaitingDuration = 0; if (this.waitingInterval) { clearInterval(this.waitingInterval); this.waitingInterval = null; } } }, { key: 'componentWillReceiveProps', value: function componentWillReceiveProps(nextProps) { var _this2 = this; if (nextProps.src !== this.props.src) { this.video = null; this.setState({ videoURL: nextProps.src }, function () { _this2.play(); }); } } }, { key: 'getVideoSRC', value: function getVideoSRC() { var videoSRC = void 0; if (this.props.src) { videoSRC = this.props.src; } else if (this.props.children) { _react2.default.Children.toArray(this.props.children).filter(_utils.isVideoChild).map(function (component) { var componentProps = void 0; if (typeof component.type === 'string' && component.type === 'source') { componentProps = (0, _extends3.default)({}, component.props); } videoSRC = componentProps.src; }); } return videoSRC || null; } }, { key: 'setVideoURL', value: function setVideoURL() { var videoURL = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.getVideoSRC(); this.methodCalls('setVideoURL'); if (videoURL !== this.state.videoURL) { this.methodCalls('setVideoURL', videoURL); this.setState({ videoURL: videoURL }); } } // get all video properties }, { key: 'getProperties', value: function getProperties() { var _this3 = this; if (!this.video) { return null; } return _utils.mediaProperties.reduce(function (properties, key) { properties[key] = _this3.video[key]; return properties; }, {}); } // get playback rate }, { key: 'setContentLoading', value: function setContentLoading() { var contentLoading = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true; var actions = this.props.actions; if (this.isVideoPlayed === contentLoading) { this.isVideoPlayed = !contentLoading; actions.handleContentLoading(contentLoading); } } }, { key: 'play', value: function play() { var _this4 = this; var attempts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; var forceToPlay = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; if (this.isSafe) { this.setContentLoading(false); var forceAutoPlay = this.props.forceAutoPlay, _state = this.state, allowToPlay = _state.allowToPlay, ad = _state.ad; if (allowToPlay || forceToPlay) { // const { muted } = this.props; this.methodCalls('play', attempts); var promise = this.video.play(); if (promise) { promise.then(function () { _this4.adPlayEvent(); var _props = _this4.props, onFirstPlayAttempt = _props.onFirstPlayAttempt, onFirstPlayAdAttempt = _props.onFirstPlayAdAttempt; if (_this4.isFirstTimeToPlay) { _this4.isFirstTimeToPlay = false; if (!ad.isPlaying && onFirstPlayAttempt) { onFirstPlayAttempt(); } if (ad.isPlaying && onFirstPlayAdAttempt) { onFirstPlayAdAttempt(); } } }).catch(function (error) { var isNotAllowedError = error && error.name === 'NotAllowedError'; _this4.error(error); if (forceAutoPlay) { if (isNotAllowedError) { _this4.muted = true; } if (attempts < 10) { setTimeout(function () { return _this4.play(attempts + 1); }, 200); } } else if (isNotAllowedError) { _this4.allowToAutoPlay = false; } }); return promise; } } } } // pause the video }, { key: 'pause', value: function pause() { var sendEvent = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true; this.methodCalls('pause'); if (sendEvent) { this.adPausedEvent(); } if (this.isSafe) { this.video.pause(); } } // Change the video source and re-load the video: }, { key: 'load', value: function load() { this.methodCalls('load'); if (this.isSafe) { this.video.load(); } } // Add a new text track to the video }, { key: 'addTextTrack', value: function addTextTrack() { this.methodCalls('addTextTrack'); if (this.isSafe) { var _video; (_video = this.video).addTextTrack.apply(_video, arguments); } } // Check if your browser can play different types of video: }, { key: 'canPlayType', value: function canPlayType() { this.methodCalls('canPlayType'); if (this.isSafe) { var _video2; (_video2 = this.video).canPlayType.apply(_video2, arguments); } } // toggle play }, { key: 'togglePlay', value: function togglePlay() { this.methodCalls('togglePlay'); if (this.isSafe) { if (this.video.paused) { this.play(); } else { this.pause(); } } } // seek video by time }, { key: 'seek', value: function seek(time) { this.methodCalls('time'); if (this.isSafe) { try { this.currentTime = time; } catch (e) { this.error('seek', e); } } } // jump forward x seconds }, { key: 'forward', value: function forward(seconds) { this.methodCalls('forward', seconds); if (this.isSafe) { this.seek(this.video.currentTime + seconds); } } // jump back x seconds }, { key: 'replay', value: function replay(seconds) { this.methodCalls('replay', seconds); if (this.isSafe) { this.forward(-seconds); } } // enter or exist full screen }, { key: 'toggleFullscreen', value: function toggleFullscreen() { this.methodCalls('toggleFullscreen'); var _props2 = this.props, player = _props2.player, actions = _props2.actions; actions.toggleFullscreen(player); } // Fired when the user agent // begins looking for media data }, { key: 'handleLoadStart', value: function handleLoadStart() { this.methodCalls('handleLoadStart'); var _props3 = this.props, actions = _props3.actions, onLoadStart = _props3.onLoadStart; actions.handleLoadStart(this.getProperties()); if (!this.delayToStartVideoTimer || !this.delayToStartVideoAdTimer) { this.delayToStartVideoAdTimer = (0, _utils.startTimer)(); this.delayToStartVideoTimer = (0, _utils.startTimer)(); } if (onLoadStart) { onLoadStart.apply(undefined, arguments); } } // A handler for events that // signal that waiting has ended }, { key: 'handleCanPlay', value: function handleCanPlay() { this.methodCalls('handleCanPlay'); var _props4 = this.props, actions = _props4.actions, onCanPlay = _props4.onCanPlay; actions.handleCanPlay(this.getProperties()); if (onCanPlay) { onCanPlay.apply(undefined, arguments); } } // A handler for events that // signal that waiting has ended }, { key: 'handleCanPlayThrough', value: function handleCanPlayThrough() { this.methodCalls('handleCanPlayThrough'); var _props5 = this.props, actions = _props5.actions, onCanPlayThrough = _props5.onCanPlayThrough; // Calculate exact delay to start playing if (this.delayToStartVideoTimer && this.isFirstTimeToPlay) { this.handleDelayToStartPlaying(); this.handleDelayToAdStartPlaying(); } else { if (this.state.currentError) { if (this.state.currentError.isFatal) { this.setWaitingFlag(); } this.setState({ currentError: null }); } this.handleWaitingDuration(); } actions.handleCanPlayThrough(this.getProperties()); if (onCanPlayThrough) { onCanPlayThrough.apply(undefined, arguments); } } }, { key: 'handleDelayToStartPlaying', value: function handleDelayToStartPlaying() { var onStartFirstTime = this.props.onStartFirstTime, ad = this.state.ad; if (!ad.isPlaying && onStartFirstTime) { onStartFirstTime({ quality: this.trackQuality, delayToStartPlaying: this.delayToStartVideoTimer.end() / 1000 }); } } }, { key: 'handleDelayToAdStartPlaying', value: function handleDelayToAdStartPlaying() { var onAdStartFirstTime = this.props.onAdStartFirstTime, ad = this.state.ad; if (ad.isPlaying && onAdStartFirstTime) { onAdStartFirstTime({ delayToStartPlaying: this.delayToStartVideoAdTimer.end() / 1000 }); } } }, { key: 'handleWaitingDuration', value: function handleWaitingDuration() { var removeInterval = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true; if (this.videoWaitingTimer) { if (removeInterval) { clearInterval(this.waitingInterval); } var onWaitingStop = this.props.onWaitingStop, currentWaitingDuration = this.videoWaitingTimer.end() / 1000; if (currentWaitingDuration > 0.1) { this.totalWaitingDuration += currentWaitingDuration; if (onWaitingStop) { onWaitingStop({ quality: this.trackQuality, waitingDuration: currentWaitingDuration, totalWaitingDuration: this.totalWaitingDuration }); } } this.videoWaitingTimer = null; } } }, { key: 'handlePlaying', // A handler for events that // signal that waiting has ended value: function handlePlaying() { this.methodCalls('handlePlaying'); var _props6 = this.props, actions = _props6.actions, onPlaying = _props6.onPlaying; actions.handlePlaying(this.getProperties()); if (onPlaying) { onPlaying.apply(undefined, arguments); } } // Fired whenever the media has been started }, { key: 'handlePlay', value: function handlePlay() { this.methodCalls('handlePlay'); var _props7 = this.props, actions = _props7.actions, onPlay = _props7.onPlay; actions.handlePlay(this.getProperties()); if (onPlay) { onPlay.apply(undefined, arguments); } } // Fired whenever the media has been paused }, { key: 'handlePause', value: function handlePause() { this.methodCalls('handlePause'); var _props8 = this.props, actions = _props8.actions, onPause = _props8.onPause; actions.handlePause(this.getProperties()); if (onPause) { onPause.apply(undefined, arguments); } } // Fired when the duration of // the media resource is first known or changed }, { key: 'handleDurationChange', value: function handleDurationChange() { this.methodCalls('handleDurationChange'); var _props9 = this.props, actions = _props9.actions, onDurationChange = _props9.onDurationChange; actions.handleDurationChange(this.getProperties()); if (onDurationChange) { onDurationChange.apply(undefined, arguments); } } // Fired while the user agent // is downloading media data }, { key: 'handleProgress', value: function handleProgress() { this.methodCalls('handleProgress'); var _props10 = this.props, actions = _props10.actions, onProgress = _props10.onProgress; if (this.video) { actions.handleProgressChange(this.getProperties()); } if (onProgress) { onProgress.apply(undefined, arguments); } } // Fired when the end of the media resource // is reached (currentTime == duration) }, { key: 'handleEnded', value: function handleEnded() { this.methodCalls('handleEnded'); var _props11 = this.props, loop = _props11.loop, player = _props11.player, actions = _props11.actions, onEnded = _props11.onEnded, source = this.state.ad.source; if (source) { this.adHandleEnd(); } else { if (loop) { this.seek(0); this.play(); } else if (!player.paused) { this.pause(); } actions.handleEnd(this.getProperties()); if (onEnded) { onEnded.apply(undefined, arguments); } } } // Fired whenever the player // is jumping to a new time }, { key: 'handleSeeking', value: function handleSeeking() { this.methodCalls('handleSeeking'); if (this.video.paused) { this.setWaitingFlag(); } var _props12 = this.props, actions = _props12.actions, onSeeking = _props12.onSeeking; actions.handleSeeking(this.getProperties()); if (onSeeking) { onSeeking.apply(undefined, arguments); } } // Fired when the player has // finished jumping to a new time }, { key: 'handleSeeked', value: function handleSeeked() { this.methodCalls('handleSeeked'); var _props13 = this.props, actions = _props13.actions, onSeeked = _props13.onSeeked; actions.handleSeeked(this.getProperties()); if (onSeeked) { onSeeked.apply(undefined, arguments); } } // Fires when the browser is // intentionally not getting media data }, { key: 'handleSuspend', value: function handleSuspend() { this.methodCalls('handleSuspend'); var _props14 = this.props, actions = _props14.actions, onSuspend = _props14.onSuspend; actions.handleSuspend(this.getProperties()); if (onSuspend) { onSuspend.apply(undefined, arguments); } } // Fires when the loading of an audio/video is aborted }, { key: 'handleAbort', value: function handleAbort() { this.methodCalls('handleAbort'); var _props15 = this.props, actions = _props15.actions, onAbort = _props15.onAbort; actions.handleAbort(this.getProperties()); if (onAbort) { onAbort.apply(undefined, arguments); } } // Fires when the current playlist is empty }, { key: 'handleEmptied', value: function handleEmptied() { this.methodCalls('handleEmptied'); var _props16 = this.props, actions = _props16.actions, onEmptied = _props16.onEmptied; actions.handleEmptied(this.getProperties()); if (onEmptied) { onEmptied.apply(undefined, arguments); } } // Fires when the browser is trying to // get media data, but data is not available }, { key: 'handleStalled', value: function handleStalled() { this.methodCalls('handleStalled'); var _props17 = this.props, actions = _props17.actions, onStalled = _props17.onStalled; actions.handleStalled(this.getProperties()); if (onStalled) { onStalled.apply(undefined, arguments); } } // Fires when the browser has loaded // meta data for the audio/video }, { key: 'handleLoadedMetaData', value: function handleLoadedMetaData() { this.methodCalls('handleLoadedMetaData'); if (this.isSafe) { var _props18 = this.props, actions = _props18.actions, onLoadedMetadata = _props18.onLoadedMetadata, adsTagUrl = _props18.adsTagUrl, isCompleted = this.state.ad.isCompleted; actions.handleLoadedMetaData(this.getProperties()); if (this.inlinePlay && adsTagUrl && isCompleted) { this.play(); } else { this.setContentLoading(false); } if (onLoadedMetadata) { onLoadedMetadata.apply(undefined, arguments); } } } // Fires when the browser has loaded // the current frame of the audio/video }, { key: 'handleLoadedData', value: function handleLoadedData() { this.methodCalls('handleLoadedData'); var _props19 = this.props, actions = _props19.actions, onLoadedData = _props19.onLoadedData, startTime = _props19.startTime, isPlaying = this.state.ad.isPlaying; actions.handleLoadedData(this.getProperties()); if (!isPlaying && startTime && startTime > 0) { this.currentTime = startTime; } if (onLoadedData) { onLoadedData.apply(undefined, arguments); } if (this.autoPlay) { this.play(); } else { this.setContentLoading(false); } } // Fired whenever the media begins waiting }, { key: 'handleWaiting', value: function handleWaiting() { this.methodCalls('handleWaiting', this.props.player); var _props20 = this.props, actions = _props20.actions, onWaiting = _props20.onWaiting; this.setWaitingFlag(); actions.handleWaiting(this.getProperties()); if (onWaiting) { onWaiting.apply(undefined, arguments); } } }, { key: 'setWaitingFlag', value: function setWaitingFlag() { var _this5 = this; var currentTime = this.props.player.currentTime; if (!this.videoWaitingTimer && currentTime) { this.videoWaitingTimer = (0, _utils.startTimer)(); this.waitingInterval = setInterval(function () { _this5.handleWaitingDuration(false); _this5.handleTimeUpdate(); if (_this5.videoWaitingTimer) { _this5.videoWaitingTimer.end(); } _this5.videoWaitingTimer = (0, _utils.startTimer)(); }, this.metricIntervalTimeout); } } // Fires when the current // playback position has changed }, { key: 'handleTimeUpdate', value: function handleTimeUpdate() { // reset waiting flag until current time if it set. if (this.isSafe) { if (this.videoWaitingTimer) { this.handleWaitingDuration(); this.setWaitingFlag(); } var _props21 = this.props, actions = _props21.actions, onTimeUpdate = _props21.onTimeUpdate, onSecondsPlayedReached = _props21.onSecondsPlayedReached, _props21$targetTotalT = _props21.targetTotalTime, targetTotalTime = _props21$targetTotalT === undefined ? 10 : _props21$targetTotalT, _props21$player = _props21.player, currentTime = _props21$player.currentTime, duration = _props21$player.duration, hls = _props21$player.hls, isLive = _props21$player.isLive, ad = this.state.ad, timeRanges = this.video.played; var secondsPlayed = 0, percentPlayed = 0; if (duration && timeRanges) { for (var i = 0; i < timeRanges.length; i++) { secondsPlayed = secondsPlayed + (timeRanges.end(i) - timeRanges.start(i)); } percentPlayed = 100 / duration * secondsPlayed; } actions.handleTimeUpdate(this.getProperties(), secondsPlayed, percentPlayed, this.totalWaitingDuration); if (isLive && hls && hls.levels[hls.currentLevel] && hls.levels[hls.currentLevel].details) { var targetDuration = hls.levels[hls.currentLevel].details.targetduration, liveSync = hls.config.liveSyncDurationCount, liveOffset = targetDuration * liveSync, liveTime = duration - liveOffset, latency = liveTime - currentTime; actions.handleMediaLatencyChange(liveTime, latency); } if (!ad.isPlaying && onSecondsPlayedReached && secondsPlayed >= targetTotalTime && !this.isReachedSecond) { this.isReachedSecond = true; onSecondsPlayedReached.apply(undefined, arguments); } if (onTimeUpdate) { onTimeUpdate.apply(undefined, arguments); } } } /** * Fires when the playing speed of the audio/video is changed */ }, { key: 'handleRateChange', value: function handleRateChange() { this.methodCalls('handleRateChange'); var _props22 = this.props, actions = _props22.actions, onRateChange = _props22.onRateChange; actions.handleRateChange(this.getProperties()); if (onRateChange) { onRateChange.apply(undefined, arguments); } } // Fires when the volume has been changed }, { key: 'handleVolumeChange', value: function handleVolumeChange() { this.methodCalls('handleVolumeChange'); var _props23 = this.props, actions = _props23.actions, onVolumeChange = _props23.onVolumeChange; actions.handleVolumeChange(this.getProperties()); if (onVolumeChange) { onVolumeChange.apply(undefined, arguments); } } // Fires when an error occurred // during the loading of an audio/video }, { key: 'handleError', value: function handleError(type, data) { var reason = (0, _utils.getErrorSchema)(data); this.error(type, data, reason); var _props24 = this.props, actions = _props24.actions, onError = _props24.onError; actions.handleError(this.getProperties()); if (onError) { onError(type, data, reason); } if (this.isFirstTimeToPlay) { this.handleStartupError(reason); } this.setState({ currentError: reason }); if (reason && reason.isFatal && this.videoWaitingTimer) { this.handleWaitingDuration(); } } }, { key: 'handleStartupError', value: function handleStartupError(reason) { this.methodCalls('handleStartupError', reason); var _props25 = this.props, onFirstPlayAttempt = _props25.onFirstPlayAttempt, onStartError = _props25.onStartError, ad = this.state.ad; if (!ad.isPlaying && this.isFirstTimeToPlay && onFirstPlayAttempt) { this.isFirstTimeToPlay = false; onFirstPlayAttempt(); } if (reason && reason.type && reason.detail && onStartError) { onStartError(reason, ad.isPlaying); } if (ad.isPlaying && (!reason || reason.isFatal)) { this.adEvent('error'); this.destroyAd(); } } }, { key: 'handleResize', value: function handleResize() { this.methodCalls('handleResize'); var _props26 = this.props, actions = _props26.actions, onResize = _props26.onResize; actions.handleResize(this.getProperties()); if (onResize) { onResize.apply(undefined, arguments); } } }, { key: 'handleVideoContentInit', value: function () { var _ref2 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee2() { var _props27, actions, adsTagUrl, onVASTLoadedFirstTime, delayToLoadVastTimer, VAST, _VAST$, mediaFiles, videoClicks, skipOn, adTitle; return _regenerator2.default.wrap(function _callee2$(_context2) { while (1) { switch (_context2.prev = _context2.next) { case 0: this.methodCalls('handleVideoContentInit'); _props27 = this.props, actions = _props27.actions, adsTagUrl = _props27.adsTagUrl, onVASTLoadedFirstTime = _props27.onVASTLoadedFirstTime; if (!adsTagUrl) { _context2.next = 22; break; } _context2.prev = 3; delayToLoadVastTimer = (0, _utils.startTimer)(); this.log('getting VAST data'); _context2.next = 8; return (0, _vastParser.handleVAST)(adsTagUrl); case 8: VAST = _context2.sent; this.log('VAST data', VAST); if (VAST && VAST.length) { _VAST$ = VAST[0], mediaFiles = _VAST$.mediaFiles, videoClicks = _VAST$.videoClicks, skipOn = _VAST$.skipOn, adTitle = _VAST$.adTitle; this.setState(function (_ref3) { var ad = _ref3.ad; return { ad: (0, _extends3.default)({}, ad, { source: mediaFiles[0].URL, clickThroughUrl: videoClicks || null, skipTimeOffset: skipOn ? skipOn + 1 : null, name: adTitle, isPlaying: true }), allowToPlay: true, videoURL: mediaFiles[0].URL }; }); this.adEvent('loaded'); if (onVASTLoadedFirstTime) { onVASTLoadedFirstTime({ delayToLoad: delayToLoadVastTimer.end() / 1000 }); } if (this.video) { this.video.addEventListener('timeupdate', this.adHandleElapsedTime); } actions.handleAdStart(); } _context2.next = 20; break; case 13: _context2.prev = 13; _context2.t0 = _context2['catch'](3); // this.handleStartupError({ // type: 'VAST_ERROR', // detail: error // }); this.setVideoURL(); this.error(_context2.t0); this.adEvent('error'); this.destroyAd(); this.allowToPlay = true; case 20: _context2.next = 24; break; case 22: this.setVideoURL(); this.allowToPlay = true; case 24: case 'end': return _context2.stop(); } } }, _callee2, this, [[3, 13]]); })); function handleVideoContentInit() { return _ref2.apply(this, arguments); } return handleVideoContentInit; }() }, { key: 'methodCalls', value: function methodCalls() { for (var _len = arguments.length, logs = Array(_len), _key = 0; _key < _len; _key++) { logs[_key] = arguments[_key]; } this.log.apply(this, ['Method: '].concat(logs)); } }, { key: 'error', value: function error() { if (this.props.debugMode) { var _console; for (var _len2 = arguments.length, logs = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { logs[_key2] = arguments[_key2]; } (_console = console).error.apply(_console, ['VIDEO_REACT'].concat(logs)); } } }, { key: 'log', value: function log() { if (this.props.debugMode) { var _console2; for (var _len3 = arguments.length, logs = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) { logs[_key3] = arguments[_key3]; } (_console2 = console).log.apply(_console2, ['VIDEO_REACT'].concat(logs)); } } /* * ////////////////////////////// ADS METHODS ////////////////////////////// */ }, { key: 'adEvent', value: function adEvent(event) { var sendPlayerEvent = this.props.sendPlayerEvent, name = this.state.ad.name; if (sendPlayerEvent) { sendPlayerEvent('Ads', event, name); } } }, { key: 'adPlayEvent', value: function adPlayEvent() { var _state$ad = this.state.ad, source = _state$ad.source, isPlaying = _state$ad.isPlaying; if (source) { this.adEvent(isPlaying ? 'play' : 'resume'); this.setState(function (_ref4) { var ad = _ref4.ad; return { ad: (0, _extends3.default)({}, ad, { isPlaying: true }) }; }); this.isAdPlaying(true); } } }, { key: 'adPausedEvent', value: function adPausedEvent() { var source = this.state.ad.source; if (source) { this.adEvent('paused'); this.setState(function (_ref5) { var ad = _ref5.ad; return { ad: (0, _extends3.default)({}, ad, { isPlaying: false }) }; }); } } }, { key: 'adEndEvent', value: function adEndEvent() { this.adEvent('complete'); } }, { key: 'adClickEvent', value: function adClickEvent() { this.adEvent('clicked'); } }, { key: 'adSkip', value: function adSkip() { this.adEvent('skip'); this.adHandleEnd(false); } }, { key: 'adMoreInfo', value: function adMoreInfo() { this.pause(false); this.adClickEvent(); } }, { key: 'destroyAd', value: function destroyAd() { var _this6 = this; this.methodCalls('destroyAd'); if (this.delayToStartVideoTimer) { this.delayToStartVideoTimer.end(); } this.delayToStartVideoTimer = (0, _utils.startTimer)(); this.isFirstTimeToPlay = true; this.pause(); var actions = this.props.actions; actions.handleAdEnded(); this.setState(function (_ref6) { var ad = _ref6.ad; return { ad: (0, _extends3.default)({}, ad, _this6.defaultAdState, { isPlayed: false, isPlaying: false, isCompleted: true }), allowToAutoPlay: true, allowToPlay: true }; }); this.isAdPlaying(false); this.setContentLoading(true); if (this.video) { this.video.removeEventListener('timeupdate', this.adHandleElapsedTime); this.video = null; } this.setVideoURL(); } }, { key: 'adHandleEnd', value: function adHandleEnd() { var sendEvent = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true; this.methodCalls('handleAdEnded'); if (sendEvent) { this.adEndEvent(); } this.destroyAd(); } }, { key: 'adHandleElapsedTime', value: function adHandleElapsedTime() { this.methodCalls('adHandleElapsedTime'); if (this.isSafe) { var duration = Math.ceil(this.video.duration), currentTime = Math.ceil(this.video.currentTime), time = Math.abs(currentTime - duration); if (time !== this.state.ad.time) { var states = { time: time }; if (this.state.ad.skipTimeOffset) { states.skipOn = this.state.ad.skipTimeOffset - currentTime; } this.setState(function (_ref7) { var ad = _ref7.ad; return { ad: (0, _extends3.default)({}, ad, states) }; }); } } } }, { key: 'isAdPlaying', value: function isAdPlaying(_isAdPlaying) { this.methodCalls('isAdPlaying', _isAdPlaying); var onAdPlaying = this.props.onAdPlaying, isPlayed = this.state.ad.isPlayed; if (_isAdPlaying !== isPlayed) { if (onAdPlaying) { onAdPlaying(_isAdPlaying); } if (_isAdPlaying !== this.state.ad.isPlayed) { this.setState(function (_ref8) { var ad = _ref8.ad; return { ad: (0, _extends3.default)({}, ad, { isPlayed: _isAdPlaying }) }; }); } } } }, { key: 'render', value: function render() { var _this7 = this; return _react2.default.createElement( 'div', { className: 'react-video-holder' }, this.state.ad && this.state.ad.isPlayed && _react2.default.createElement(_AdControllers2.default, { onSkip: function onSkip() { return _this7.adSkip(); }, onLinkClick: function onLinkClick() { return _this7.adMoreInfo(); }, duration: this.state.ad.time, skipOn: this.state.ad.skipOn, URL: this.state.ad.clickThroughUrl }), _react2.default.createElement( 'video', { className: (0, _classnames2.default)('video-react-video', this.props.className), id: this.props.videoId, crossOrigin: this.props.crossOrigin, ref: function ref(c) { _this7.video = c; }, muted: this.props.muted, preload: this.props.preload, loop: this.props.loop, autoPlay: this.state.allowToPlay && this.autoPlay, poster: this.props.poster, src: this.state.videoURL, onLoadStart: this.handleLoadStart, onWaiting: this.handleWaiting, onCanPlay: this.handleCanPlay, onCanPlayThrough: this.handleCanPlayThrough, onPlaying: this.handlePlaying, onEnded: this.handleEnded, onSeeking: this.handleSeeking, onSeeked: this.handleSeeked, onPlay: this.handlePlay, onPause: this.handlePause, onProgress: this.handleProgress, onDurationChange: this.handleDurationChange, onError: this.handleError, onSuspend: this.handleSuspend, onAbort: this.handleAbort, onEmptied: this.handleEmptied, onStalled: this.handleStalled, onLoadedMetadata: this.handleLoadedMetaData, onLoadedData: this.handleLoadedData, onTimeUpdate: this.handleTimeUpdate, onRateChange: this.handleRateChange, onVolumeChange: this.handleVolumeChange }, this.playerSource ) ); } }, { key: 'isSafe', get: function get() { return this.state.videoURL && !!this.video; } }, { key: 'autoPlay', get: function get() { return this.state.allowToAutoPlay && this.props.autoPlay; } }, { key: 'playbackRate', get: function get() { this.methodCalls('playbackRate'); if (this.isSafe) { return this.video.playbackRate; } }, set: function set(rate) { this.methodCalls('playbackRate', rate); if (this.isSafe) { this.video.playbackRate = rate; } } }, { key: 'currentTime', set: function set(time) { this.methodCalls('currentTime', time); if (this.isSafe) { this.video.currentTime = time; } } }, { key: 'muted', get: function get() { this.methodCalls('get muted', this.video.muted); if (this.isSafe) { return this.video.muted; } }, set: function set(val) { this.methodCalls('set muted', val); if (this.isSafe) { this.video.muted = val; } } }, { key: 'volume', get: function get() { this.methodCalls('get volume', this.video.volume); if (this.isSafe) { return this.video.volume; } }, set: function set(val) { if (val > 1) { val = 1; } if (val < 0) { val = 0; } this.methodCalls('set volume', val); if (this.isSafe) { this.video.volume = val; } } // video width }, { key: 'videoWidth', get: function get() { this.methodCalls('get videoWidth', this.video.videoWidth); if (this.isSafe) { return this.video.videoWidth; } } // video height }, { key: 'videoHeight', get: function get() { this.methodCalls('get videoHeight', this.video.videoHeight); if (this.isSafe) { return this.video.videoHeight; } } }, { key: 'allowToPlay', set: function set(allowToPlay) { this.methodCalls('set allowToPlay', allowToPlay); if (allowToPlay !== this.state.allowToPlay) { this.setState({ allowToPlay: allowToPlay }); } } }, { key: 'allowToAutoPlay', set: function set(allowToAutoPlay) { this.methodCalls('set allowToAutoPlay', allowToAutoPlay); if (allowToAutoPlay !== this.state.allowToAutoPlay) { this.setState({ allowToAutoPlay: allowToAutoPlay }); } } }, { key: 'trackQuality', get: function get() { var _props$player = this.props.player, tracks = _props$player.tracks, realActiveTrack = _props$player.realActiveTrack; return tracks && tracks.length > 1 && tracks.filter(function (item) { return item.id === realActiveTrack; })[0].label || null; } }, { key: 'playerSource', get: function get() { var _this8 = this; if (!this.isSafe) { return null; } var props = (0, _extends3.default)({}, this.props, { video: this.video }); var _state2 = this.state, source = _state2.ad.source, videoURL = _state2.videoURL; this.video.controls = this.video && browser.IS_MOBILE && !source; this.video.playsInline = this.video && browser.IS_MOBILE; return _react2.default.Children.toArray(this.props.children).filter(_utils.isVideoChild).map(function () { return (0, _utils.isHls)(videoURL) && !browser.IS_IOS ? _react2.default.createElement(_HLSSource2.default, (0, _extends3.default)({ key: 2 }, props, { onError: _this8.handleError, src: videoURL })) : _react2.default.createElement('source', { key: 1, src: videoURL }); }); } }]); return Video; }(_react.Component); exports.default = Video; Video.propTypes = propTypes; Video.defaultProps = defaultProps; Video.displayName = 'Video';