UNPKG

fastlion-amis

Version:

一种MIS页面生成工具

454 lines (453 loc) 21.5 kB
"use strict"; /** * @file video * @author fex */ Object.defineProperty(exports, "__esModule", { value: true }); exports.VideoRenderer = exports.HlsSource = exports.FlvSource = void 0; var tslib_1 = require("tslib"); var react_1 = (0, tslib_1.__importDefault)(require("react")); var video_react_1 = require("video-react"); var helper_1 = require("../utils/helper"); var factory_1 = require("../factory"); var tpl_builtin_1 = require("../utils/tpl-builtin"); var tpl_1 = require("../utils/tpl"); var str2seconds = function (str) { return str.indexOf(':') ? str .split(':') .reverse() .reduce(function (seconds, value, index) { return seconds + (parseInt(value, 10) || 0) * Math.pow(60, index); }, 0) : parseInt(str, 10); }; // let currentPlaying: any = null; var FlvSource = /** @class */ (function (_super) { (0, tslib_1.__extends)(FlvSource, _super); function FlvSource() { var _this = _super !== null && _super.apply(this, arguments) || this; _this.loaded = false; return _this; } FlvSource.prototype.componentDidMount = function () { var _a = this.props, src = _a.src, video = _a.video, config = _a.config, manager = _a.manager, isLive = _a.isLive, autoPlay = _a.autoPlay, actions = _a.actions, setError = _a.setError; this.initFlv({ video: video, manager: manager, src: src, isLive: isLive, config: config, actions: actions, setError: setError, autoPlay: autoPlay }); }; FlvSource.prototype.componentDidUpdate = function (prevProps) { var _a, _b; var props = this.props; var autoPlay = props.autoPlay, actions = props.actions, src = props.src, setError = props.setError, isLive = props.isLive, config = props.config, video = props.video, manager = props.manager; if (src !== prevProps.src) { setError(''); (_a = this.mpegtsPlayer) === null || _a === void 0 ? void 0 : _a.destroy(); (_b = this.unsubscribe) === null || _b === void 0 ? void 0 : _b.call(this); this.loaded = false; this.initFlv({ video: video, manager: manager, src: src, isLive: isLive, config: config, actions: actions, setError: setError, autoPlay: autoPlay }); } }; FlvSource.prototype.componentWillUnmount = function () { var _a, _b; if (this.mpegtsPlayer) { this.mpegtsPlayer.destroy(); (_b = (_a = this.props).setError) === null || _b === void 0 ? void 0 : _b.call(_a, ''); } }; FlvSource.prototype.initFlv = function (_a) { var _this = this; var video = _a.video, manager = _a.manager, src = _a.src, isLive = _a.isLive, config = _a.config, actions = _a.actions, setError = _a.setError, autoPlay = _a.autoPlay; Promise.resolve().then(function () { return new Promise(function(resolve){require(['mpegts.js'], function(ret) {resolve(tslib_1.__importStar(ret));})}); }).then(function (mpegts) { video = video || (manager.video && manager.video.video); var mpegtsPlayer = mpegts.createPlayer({ type: 'flv', url: src, isLive: isLive }, config); mpegtsPlayer.attachMediaElement(video); _this.mpegtsPlayer = mpegtsPlayer; _this.unsubscribe = manager.subscribeToOperationStateChange(function (operation) { var type = operation.operation.action; if (type === 'play') { clearTimeout(_this.timer); if (!_this.loaded) { _this.loaded = true; mpegtsPlayer.load(); } mpegtsPlayer.play(); } else if (type === 'pause') { mpegtsPlayer.pause(); if (isLive) { _this.timer = setTimeout(function () { actions.seek(0); mpegtsPlayer.unload(); _this.loaded = false; }, 30000); } } }); mpegtsPlayer.on(mpegts.Events.RECOVERED_EARLY_EOF, function () { setError('直播已经结束'); }); mpegtsPlayer.on(mpegts.Events.ERROR, function () { setError('视频加载失败'); mpegtsPlayer.unload(); }); if (autoPlay) { setTimeout(function () { return actions.play(); }, 200); } }); }; FlvSource.prototype.render = function () { return (react_1.default.createElement("source", { src: this.props.src, type: this.props.type || 'video/x-flv' })); }; return FlvSource; }(react_1.default.Component)); exports.FlvSource = FlvSource; var HlsSource = /** @class */ (function (_super) { (0, tslib_1.__extends)(HlsSource, _super); function HlsSource() { var _this = _super !== null && _super.apply(this, arguments) || this; _this.loaded = false; return _this; } HlsSource.prototype.componentDidMount = function () { var _a = this.props, src = _a.src, video = _a.video, config = _a.config, manager = _a.manager, isLive = _a.isLive, autoPlay = _a.autoPlay, actions = _a.actions; this.initHls({ video: video, manager: manager, src: src, autoPlay: autoPlay, actions: actions }); }; HlsSource.prototype.componentWillUnmount = function () { if (this.hls) { this.hls.stopLoad(); this.hls.detachMedia(); } }; HlsSource.prototype.componentDidUpdate = function (prevProps) { var _a, _b, _c; var props = this.props; var autoPlay = props.autoPlay, actions = props.actions, src = props.src, isLive = props.isLive, config = props.config, video = props.video, manager = props.manager; if (src !== prevProps.src) { (_a = this.hls) === null || _a === void 0 ? void 0 : _a.stopLoad(); (_b = this.hls) === null || _b === void 0 ? void 0 : _b.detachMedia(); (_c = this.unsubscribe) === null || _c === void 0 ? void 0 : _c.call(this); this.loaded = false; this.initHls({ video: video, manager: manager, src: src, autoPlay: autoPlay, actions: actions }); } }; HlsSource.prototype.initHls = function (_a) { var _this = this; var video = _a.video, manager = _a.manager, src = _a.src, autoPlay = _a.autoPlay, actions = _a.actions; // @ts-ignore Promise.resolve().then(function () { return new Promise(function(resolve){require(['hls.js'], function(ret) {resolve(tslib_1.__importStar(ret));})}); }).then(function (_a) { var Hls = _a.default; // load hls video source base on hls.js if (Hls.isSupported()) { video = video || (manager.video && manager.video.video); var hls_1 = (_this.hls = new Hls({ autoStartLoad: false })); hls_1.attachMedia(video); hls_1.loadSource(src); _this.unsubscribe = manager.subscribeToOperationStateChange(function (operation) { var type = operation.operation.action; if (type === 'play') { if (!_this.loaded) { _this.loaded = true; hls_1.startLoad(); } video.play(); } else if (type === 'pause') { video.pause(); hls_1.stopLoad(); _this.loaded = false; } }); autoPlay && setTimeout(actions.play, 200); } }); }; HlsSource.prototype.render = function () { return (react_1.default.createElement("source", { src: this.props.src, type: this.props.type || 'application/x-mpegURL' })); }; return HlsSource; }(react_1.default.Component)); exports.HlsSource = HlsSource; var Video = /** @class */ (function (_super) { (0, tslib_1.__extends)(Video, _super); function Video(props) { var _this = _super.call(this, props) || this; _this.state = { posterInfo: null, videoState: {} }; _this.frameRef = _this.frameRef.bind(_this); _this.cursorRef = _this.cursorRef.bind(_this); _this.playerRef = _this.playerRef.bind(_this); _this.onImageLoaded = _this.onImageLoaded.bind(_this); _this.onClick = _this.onClick.bind(_this); _this.setError = _this.setError.bind(_this); return _this; } Video.prototype.onImageLoaded = function (e) { var _this = this; var image = new Image(); image.onload = function () { _this.setState({ posterInfo: { width: image.width, height: image.height } }); image = image.onload = null; }; image.src = e.target.getAttribute('src'); }; Video.prototype.frameRef = function (dom) { this.frameDom = dom; }; Video.prototype.cursorRef = function (dom) { this.cursorDom = dom; }; Video.prototype.playerRef = function (player) { var _this = this; this.player = player; if (!player) { return; } player.subscribeToStateChange(function (state) { _this.setState({ videoState: state }); // if (!state.paused) { // if ( // currentPlaying && // currentPlaying.video && // currentPlaying !== player // ) { // currentPlaying.pause(); // } // currentPlaying = player; // } if (!_this.frameDom || !_this.times) { return; } var jumpBufferDuration = _this.props.jumpBufferDuration || 0; var index = 0; var times = _this.times; var len = times.length; while (index < len - 1) { if (times[index + 1] && state.currentTime < times[index + 1] - jumpBufferDuration) { break; } index++; } if (_this.currentIndex !== index) { _this.moveCursorToIndex(index); } }); }; Video.prototype.moveCursorToIndex = function (index) { var ns = this.props.classPrefix; if (!this.frameDom || !this.cursorDom) { return; } var items = this.frameDom.querySelectorAll("." + ns + "Video-frame"); if (items && items.length && items[index]) { this.currentIndex = index; var item = items[index]; var frameRect = this.frameDom.getBoundingClientRect(); var rect = item.getBoundingClientRect(); this.cursorDom.setAttribute('style', "width: " + (rect.width - 4) + "px; height: " + (rect.height - 4) + "px; left: " + (rect.left + 2 - frameRect.left) + "px; top: " + (rect.top + 2 - frameRect.top) + "px;"); } }; Video.prototype.jumpToIndex = function (index) { if (!this.times || !this.player || !this.props.jumpFrame) { return; } var jumpBufferDuration = this.props.jumpBufferDuration || 0; var times = this.times; var player = this.player; player.seek(times[index] - jumpBufferDuration); player.play(); }; Video.prototype.onClick = function (e) { // 避免把所在 form 给提交了。 e.preventDefault(); }; Video.prototype.setError = function (error) { var player = this.player; this.setState({ error: error }); player === null || player === void 0 ? void 0 : player.pause(); }; Video.prototype.renderFrames = function () { var _this = this; var _a = this.props, frames = _a.frames, framesClassName = _a.framesClassName, columnsCount = _a.columnsCount, data = _a.data, jumpFrame = _a.jumpFrame, ns = _a.classPrefix, cx = _a.classnames; if (typeof frames === 'string' && frames[0] === '$') { frames = (0, tpl_builtin_1.resolveVariable)(frames, data); } if (!frames) { return null; } var items = []; var times = (this.times = []); Object.keys(frames).forEach(function (time) { times.push(str2seconds(time)); items.push({ time: time, src: frames[time] }); }); if (!items.length) { return null; } return (react_1.default.createElement("div", { className: cx("pos-rlt Video-frameList", framesClassName), ref: this.frameRef }, (0, helper_1.padArr)(items, columnsCount).map(function (items, i) { var restCount = columnsCount - items.length; var blankArray = []; while (restCount--) { blankArray.push(''); } return (react_1.default.createElement("div", { className: "pull-in-xxs", key: i }, react_1.default.createElement("div", { className: ns + "Hbox " + ns + "Video-frameItem" }, items.map(function (item, key) { return (react_1.default.createElement("div", { className: ns + "Hbox-col Wrapper--xxs " + ns + "Video-frame", key: key, onClick: function () { return _this.jumpToIndex(i * columnsCount + key); } }, item.src ? (react_1.default.createElement("img", { className: "w-full", alt: "poster", src: item.src })) : null, react_1.default.createElement("div", { className: ns + "Video-frameLabel" }, item.time))); }), /* 补充空白 */ restCount ? blankArray.map(function (_, index) { return (react_1.default.createElement("div", { className: ns + "Hbox-col Wrapper--xxs", key: "blank_" + index })); }) : null))); }), jumpFrame ? (react_1.default.createElement("span", { ref: this.cursorRef, className: ns + "Video-cursor" })) : null)); }; Video.prototype.renderPlayer = function () { var _a = this.props, poster = _a.poster, autoPlay = _a.autoPlay, muted = _a.muted, name = _a.name, data = _a.data, amisConfig = _a.amisConfig, locals = _a.locals, isLive = _a.isLive, minVideoDuration = _a.minVideoDuration, videoType = _a.videoType, playerClassName = _a.playerClassName, ns = _a.classPrefix, aspectRatio = _a.aspectRatio, rates = _a.rates, cx = _a.classnames; var source = (0, tpl_1.filter)(this.props.src, data, '| raw') || (0, helper_1.getPropValue)(this.props); var videoState = this.state.videoState; var highlight = videoState.duration && minVideoDuration && videoState.duration < minVideoDuration; var src = (0, tpl_1.filter)(source, data, '| raw'); var sourceNode; var error = this.state.error; if ((src && /\.flv(?:$|\?)/.test(src) && isLive) || videoType === 'video/x-flv') { sourceNode = (react_1.default.createElement(FlvSource, { autoPlay: autoPlay, order: 999.0, isLive: isLive, src: src, setError: this.setError })); } else if ((src && /\.m3u8(?:$|\?)/.test(src)) || videoType === 'application/x-mpegURL') { sourceNode = react_1.default.createElement(HlsSource, { autoPlay: autoPlay, order: 999.0, src: src }); } else { sourceNode = react_1.default.createElement("source", { src: src }); } return (react_1.default.createElement("div", { className: cx('Video-player', playerClassName) }, react_1.default.createElement(video_react_1.Player, { ref: this.playerRef, poster: (0, tpl_1.filter)(poster, data, '| raw'), src: src, autoPlay: autoPlay, muted: muted, aspectRatio: aspectRatio }, rates && rates.length ? (react_1.default.createElement(video_react_1.ControlBar, null, react_1.default.createElement(video_react_1.PlaybackRateMenuButton, { rates: rates, order: 7.1 }))) : null, react_1.default.createElement(video_react_1.BigPlayButton, { position: "center" }), sourceNode, react_1.default.createElement(video_react_1.Shortcut, { disabled: true })), error ? react_1.default.createElement("div", { className: cx('Video-error') }, error) : null, highlight ? (react_1.default.createElement("p", { className: "m-t-xs " + ns + "Text--danger" }, "\u89C6\u9891\u65F6\u957F\u5C0F\u4E8E ", minVideoDuration, " \u79D2")) : null)); }; Video.prototype.renderPosterAndPlayer = function () { var _a = this.props, poster = _a.poster, data = _a.data, locals = _a.locals, minPosterDimension = _a.minPosterDimension, cx = _a.classnames; var posterInfo = this.state.posterInfo || {}; var dimensionClassName = ''; if (posterInfo && minPosterDimension && (minPosterDimension.width || minPosterDimension.height) && (minPosterDimension.width > posterInfo.width || minPosterDimension.height > posterInfo.height)) { dimensionClassName = "Text--danger"; } return (react_1.default.createElement("div", { className: "pull-in-xs" }, react_1.default.createElement("div", { className: cx('Hbox') }, react_1.default.createElement("div", { className: cx('Hbox-col') }, react_1.default.createElement("div", { className: cx('Wrapper Wrapper--xs') }, react_1.default.createElement("img", { onLoad: this.onImageLoaded, className: "w-full", alt: "poster", src: (0, tpl_1.filter)(poster, data, '| raw') }), react_1.default.createElement("p", { className: "m-t-xs" }, "\u5C01\u9762", ' ', react_1.default.createElement("span", { className: dimensionClassName }, posterInfo.width || '-', " x ", posterInfo.height || '-'), dimensionClassName ? (react_1.default.createElement("span", null, ' ', "\u5C01\u9762\u5C3A\u5BF8\u5C0F\u4E8E", ' ', react_1.default.createElement("span", { className: cx('Text--danger') }, minPosterDimension.width || '-', " x", ' ', minPosterDimension.height || '-'))) : null))), react_1.default.createElement("div", { className: cx('Hbox-col') }, react_1.default.createElement("div", { className: cx('Wrapper Wrapper--xs') }, this.renderPlayer()))))); }; Video.prototype.render = function () { var _a = this.props, splitPoster = _a.splitPoster, className = _a.className, ns = _a.classPrefix, cx = _a.classnames; return (react_1.default.createElement("div", { className: cx("Video", className), onClick: this.onClick }, this.renderFrames(), splitPoster ? this.renderPosterAndPlayer() : this.renderPlayer())); }; Video.defaultProps = { columnsCount: 8, isLive: false, jumpFrame: true, aspectRatio: 'auto' }; return Video; }(react_1.default.Component)); exports.default = Video; var VideoRenderer = /** @class */ (function (_super) { (0, tslib_1.__extends)(VideoRenderer, _super); function VideoRenderer() { return _super !== null && _super.apply(this, arguments) || this; } VideoRenderer = (0, tslib_1.__decorate)([ (0, factory_1.Renderer)({ type: 'video' }) ], VideoRenderer); return VideoRenderer; }(Video)); exports.VideoRenderer = VideoRenderer; //# sourceMappingURL=./renderers/Video.js.map