├── .babelrc ├── .gitignore ├── README.md ├── build └── index.js ├── docs ├── bundle.js └── index.html ├── package-lock.json ├── package.json ├── src ├── Controls.json └── index.js └── webpack.config.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["@babel/preset-env"], 3 | "plugins": [ 4 | "transform-object-rest-spread", 5 | "transform-react-jsx", 6 | "@babel/plugin-proposal-class-properties" 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # react-video-js-player 2 | React wrapper for VideoJS. [Live Demo](https://karan101292.github.io/react-video-js-player/) 3 | 4 | ## Install 5 | ``` 6 | npm install --save react-video-js-player 7 | ``` 8 | 9 | ## Usage 10 | ```javascript 11 | import React, { Component } from 'react'; 12 | import VideoPlayer from 'react-video-js-player'; 13 | 14 | class VideoApp extends Component { 15 | player = {} 16 | state = { 17 | video: { 18 | src: "http://www.example.com/path/to/video.mp4", 19 | poster: "http://www.example.com/path/to/video_poster.jpg" 20 | } 21 | } 22 | 23 | onPlayerReady(player){ 24 | console.log("Player is ready: ", player); 25 | this.player = player; 26 | } 27 | 28 | onVideoPlay(duration){ 29 | console.log("Video played at: ", duration); 30 | } 31 | 32 | onVideoPause(duration){ 33 | console.log("Video paused at: ", duration); 34 | } 35 | 36 | onVideoTimeUpdate(duration){ 37 | console.log("Time updated: ", duration); 38 | } 39 | 40 | onVideoSeeking(duration){ 41 | console.log("Video seeking: ", duration); 42 | } 43 | 44 | onVideoSeeked(from, to){ 45 | console.log(`Video seeked from ${from} to ${to}`); 46 | } 47 | 48 | onVideoEnd(){ 49 | console.log("Video ended"); 50 | } 51 | 52 | render() { 53 | return ( 54 |
55 | 69 |
70 | ); 71 | } 72 | } 73 | export default VideoApp; 74 | ``` 75 | 76 | ### VideoJS APIs support: 77 | > onReady will return videojs instance. Which means you can use all the APIs provided by VideoJS.
[List of VideoJS APIs](https://docs.videojs.com/docs/api/player.html) 78 | 79 | ### VideoJS plugins support: 80 | > Since most of the VideoJS plugins needs videojs instance to get initialized, it is very easy to integrate any of the available plugins by making use of videojs instance returnd by onReady event.
[List of VideoJS plugins](https://videojs.com/plugins/) 81 | 82 | ### Available Props: 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 |
Prop NameProp TypeDefault ValueDescription
srcstring""Video file path
posterstring""Video poster file path
widthstring | numberautoVideo player width
heightstring | numberautoVideo player height
controlsbooleantrueVideo player control bar toggle
autoplaybooleanfalseVideo will start playing automatically if true
preloadstringautovideo tag preload attribute
playbackRatesarray[0.5, 1, 1.5, 2]Video speed control
hideControlsarray[]List of controls to hide. ['play','volume','seekbar','timer','playbackrates','fullscreen']
bigPlayButtonbooleantrueBig play button visibility toggle
bigPlayButtonCenteredbooleantrueBig play button center position toggle
classNamestring""Video player wrapper class. It can be used for custom player skin.
167 | 168 | ### Video tracking props: 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 |
Method NameDescription
onReadyIt will fire when video player is ready to be used. It returns videojs instance.
onPlayIt will fire when video starts playing anytime. It returns current time of the video
onPauseIt will fire when video is paused. It returns current time of the video
onTimeUpdateIt keeps firing while video is in playing state. It returns current time of the video
onSeekingIt will fire when video is being seeked using seekbar. It returns current time of the video
onSeekedIt will fire after seeking is done. It returns seek start time and seek end time for the video.
onEndIt will fire when video is finished playing.
207 | -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | My React App 6 | 7 | 8 |
9 | 10 | 11 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-video-js-player", 3 | "version": "1.1.1", 4 | "description": "React wrapper for VideoJS", 5 | "homepage": "https://github.com/karan101292/react-video-js-player#readme", 6 | "repository": "https://github.com/karan101292/react-video-js-player", 7 | "main": "build/index.js", 8 | "scripts": { 9 | "start": "webpack --watch --mode development", 10 | "build": "webpack --mode production" 11 | }, 12 | "keywords": [ 13 | "react-video-js-player", 14 | "react", 15 | "videojs" 16 | ], 17 | "author": "Karan Bhutwala", 18 | "license": "ISC", 19 | "peerDependencies": { 20 | "react": "^16.6.3" 21 | }, 22 | "dependencies": { 23 | "prop-types": "^15.6.2", 24 | "react": "^16.6.3", 25 | "webpack": "^4.26.1", 26 | "video.js": "^7.4.1" 27 | }, 28 | "devDependencies": { 29 | "@babel/core": "^7.1.2", 30 | "@babel/plugin-proposal-class-properties": "^7.1.0", 31 | "@babel/preset-env": "^7.1.0", 32 | "babel-loader": "^8.0.4", 33 | "babel-plugin-transform-object-rest-spread": "^7.0.0-beta.3", 34 | "babel-plugin-transform-react-jsx": "^6.24.1", 35 | "css-loader": "^1.0.0", 36 | "file-loader": "^2.0.0", 37 | "image-webpack-loader": "^4.5.0", 38 | "node-sass": "^4.9.4", 39 | "sass-loader": "^7.1.0", 40 | "style-loader": "^0.23.1", 41 | "url-loader": "^1.1.2", 42 | "webpack-cli": "^3.1.2" 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Controls.json: -------------------------------------------------------------------------------- 1 | { 2 | "play": "playToggle", 3 | "volume": "volumePanel", 4 | "seekbar": "progressControl", 5 | "timer": "remainingTimeDisplay", 6 | "playbackrates": "playbackRateMenuButton", 7 | "fullscreen": "fullscreenToggle" 8 | } -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import Controls from './Controls.json'; 4 | import videojs from 'video.js'; 5 | import 'video.js/dist/video-js.css'; 6 | 7 | class VideoPlayer extends Component { 8 | playerId = `video-player-${(new Date) * 1}` 9 | player = {}; 10 | componentDidMount() { 11 | this.init_player(this.props); 12 | this.init_player_events(this.props); 13 | } 14 | 15 | componentWillReceiveProps(nextProps){ 16 | this.set_controls_visibility(this.player, nextProps.hideControls); 17 | if(this.props.src !== nextProps.src){ 18 | this.init_player(nextProps); 19 | } 20 | } 21 | 22 | componentWillUnmount() { 23 | if (this.player) this.player.dispose(); 24 | } 25 | 26 | init_player(props) { 27 | const playerOptions = this.generate_player_options(props); 28 | this.player = videojs(document.querySelector(`#${this.playerId}`), playerOptions); 29 | this.player.src(props.src) 30 | this.player.poster(props.poster) 31 | this.set_controls_visibility(this.player, props.hideControls); 32 | } 33 | 34 | generate_player_options(props){ 35 | const playerOptions = {}; 36 | playerOptions.controls = props.controls; 37 | playerOptions.autoplay = props.autoplay; 38 | playerOptions.preload = props.preload; 39 | playerOptions.width = props.width; 40 | playerOptions.height = props.height; 41 | playerOptions.bigPlayButton = props.bigPlayButton; 42 | const hidePlaybackRates = props.hidePlaybackRates || props.hideControls.includes('playbackrates'); 43 | if (!hidePlaybackRates) playerOptions.playbackRates = props.playbackRates; 44 | return playerOptions; 45 | } 46 | 47 | set_controls_visibility(player, hidden_controls){ 48 | Object.keys(Controls).map(x => { player.controlBar[Controls[x]].show() }) 49 | hidden_controls.map(x => { player.controlBar[Controls[x]].hide() }); 50 | } 51 | 52 | init_player_events(props) { 53 | let currentTime = 0; 54 | let previousTime = 0; 55 | let position = 0; 56 | 57 | this.player.ready(() => { 58 | props.onReady(this.player); 59 | window.player = this.player; 60 | }); 61 | this.player.on('play', () => { 62 | props.onPlay(this.player.currentTime()); 63 | }); 64 | this.player.on('pause', () => { 65 | props.onPause(this.player.currentTime()); 66 | }); 67 | this.player.on('timeupdate', (e) => { 68 | props.onTimeUpdate(this.player.currentTime()); 69 | previousTime = currentTime; 70 | currentTime = this.player.currentTime(); 71 | if (previousTime < currentTime) { 72 | position = previousTime; 73 | previousTime = currentTime; 74 | } 75 | }); 76 | this.player.on('seeking', () => { 77 | this.player.off('timeupdate', () => { }); 78 | this.player.one('seeked', () => { }); 79 | props.onSeeking(this.player.currentTime()); 80 | }); 81 | 82 | this.player.on('seeked', () => { 83 | let completeTime = Math.floor(this.player.currentTime()); 84 | props.onSeeked(position, completeTime); 85 | }); 86 | this.player.on('ended', () => { 87 | props.onEnd(); 88 | }); 89 | } 90 | 91 | render() { 92 | return ( 93 | 94 | ) 95 | } 96 | } 97 | 98 | VideoPlayer.propTypes = { 99 | src: PropTypes.string, 100 | poster: PropTypes.string, 101 | controls: PropTypes.bool, 102 | autoplay: PropTypes.bool, 103 | preload: PropTypes.oneOf(['auto', 'none', 'metadata']), 104 | width: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), 105 | height: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), 106 | hideControls: PropTypes.arrayOf(PropTypes.string), 107 | bigPlayButton: PropTypes.bool, 108 | bigPlayButtonCentered: PropTypes.bool, 109 | onReady: PropTypes.func, 110 | onPlay: PropTypes.func, 111 | onPause: PropTypes.func, 112 | onTimeUpdate: PropTypes.func, 113 | onSeeking: PropTypes.func, 114 | onSeeked: PropTypes.func, 115 | onEnd: PropTypes.func, 116 | playbackRates: PropTypes.arrayOf(PropTypes.number), 117 | hidePlaybackRates: PropTypes.bool, 118 | className: PropTypes.string 119 | } 120 | 121 | VideoPlayer.defaultProps = { 122 | src: "", 123 | poster: "", 124 | controls: true, 125 | autoplay: false, 126 | preload: 'auto', 127 | playbackRates: [0.5, 1, 1.5, 2], 128 | hidePlaybackRates: false, 129 | className: "", 130 | hideControls: [], 131 | bigPlayButton: true, 132 | bigPlayButtonCentered: true, 133 | onReady: () => { }, 134 | onPlay: () => { }, 135 | onPause: () => { }, 136 | onTimeUpdate: () => { }, 137 | onSeeking: () => { }, 138 | onSeeked: () => { }, 139 | onEnd: () => { } 140 | } 141 | 142 | 143 | export default VideoPlayer; -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | module.exports = { 3 | entry: './src/index.js', 4 | output: { 5 | path: path.resolve(__dirname, 'build'), 6 | filename: 'index.js', 7 | libraryTarget: 'commonjs2' 8 | }, 9 | module: { 10 | rules: [ 11 | { 12 | test: /\.js$/, 13 | include: path.resolve(__dirname, 'src'), 14 | exclude: /(node_modules|bower_components)/, 15 | use: { 16 | loader: 'babel-loader', 17 | options: { 18 | presets: ['@babel/preset-env'] 19 | } 20 | } 21 | }, 22 | { 23 | test: /\.css$/, 24 | use: ['style-loader', 'css-loader'] 25 | }, 26 | { 27 | test: /\.scss$/, 28 | use: [ "style-loader", "css-loader", "sass-loader" ] 29 | } 30 | ] 31 | }, 32 | externals: { 33 | 'react': 'commonjs react' 34 | } 35 | }; 36 | --------------------------------------------------------------------------------