Skip to content

Commit

Permalink
Prime Youtube and Vimeo players with a blank video
Browse files Browse the repository at this point in the history
Fixes #7
  • Loading branch information
cookpete committed Dec 24, 2015
1 parent 430307e commit 31b7d3d
Show file tree
Hide file tree
Showing 9 changed files with 76 additions and 38 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ All notable changes to this project will be documented in this file. This projec

### Unreleased

* Fix [YouTube and Vimeo autoplay bug](https://github.com/CookPete/react-player/issues/7)
* [Full commit list](https://github.com/CookPete/react-player/compare/v0.2.1...master)


Expand Down
10 changes: 7 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,13 @@ These props allow you to override the parameters for the various players

Prop | Description
---- | -----------
soundcloudConfig | An object containing configuration for the SoundCloud player. Includes `clientId`, which can be used to override the default `client_id`
vimeoConfig | An object containing configuration for the Vimeo player. Includes `iframeParams`, which maps to the [parameters accepted by the Vimeo iframe player](https://developer.vimeo.com/player/embedding#universal-parameters)
youtubeConfig | An object containing configuration for the YouTube player. Includes `playerVars`, which maps to the [parameters accepted by the YouTube iframe player](https://developers.google.com/youtube/player_parameters?playerVersion=HTML5)
soundcloudConfig | Configuration object for the SoundCloud player. Set `clientId`, to your own SoundCloud app [client ID](https://soundcloud.com/you/apps)
vimeoConfig | Configuration object for the Vimeo player. Set `iframeParams`, to override the [default params](https://developer.vimeo.com/player/embedding#universal-parameters). Set `preload` for [preloading](#preloading)
youtubeConfig | Configuration object for the YouTube player. Set `playerVars`, to override the [default player vars](https://developers.google.com/youtube/player_parameters?playerVersion=HTML5). Set `preload` for [preloading](#preloading)

##### Preloading

Both `youtubeConfig` and `vimeoConfig` props can take a `preload` value. Setting this to `true` will play a short, silent video in the background when `ReactPlayer` first mounts. This fixes a [bug](https://github.com/CookPete/react-player/issues/7) where videos would not play when loaded in a background browser tab.

### Methods

Expand Down
13 changes: 11 additions & 2 deletions src/ReactPlayer.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,17 @@ export default class ReactPlayer extends Component {
}
renderPlayer = Player => {
const active = Player.canPlay(this.props.url)
const props = active ? { ...this.props, ref: 'player' } : {}
return <Player key={Player.name} {...props} />
const { youtubeConfig, soundcloudConfig, vimeoConfig, ...activeProps } = this.props
const props = active ? { ...activeProps, ref: 'player' } : {}
return (
<Player
key={Player.name}
youtubeConfig={youtubeConfig}
soundcloudConfig={soundcloudConfig}
vimeoConfig={vimeoConfig}
{...props}
/>
)
}
render () {
const style = {
Expand Down
20 changes: 11 additions & 9 deletions src/players/Base.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,22 @@ export default class Base extends Component {
static defaultProps = defaultProps
componentDidMount () {
this.update()
if (this.props.url) {
this.load(this.props.url)
}
}
componentWillUnmount () {
this.stop()
clearTimeout(this.updateTimeout)
}
componentWillReceiveProps (nextProps) {
// Invoke player methods based on incoming props
if (this.props.url !== nextProps.url) {
if (nextProps.url) {
this.play(nextProps.url)
this.props.onProgress({ played: 0, loaded: 0 })
} else {
this.stop()
clearTimeout(this.updateTimeout)
}
if (this.props.url !== nextProps.url && nextProps.url) {
this.load(nextProps.url, nextProps.playing)
this.props.onProgress({ played: 0, loaded: 0 }) // Needed?
} else if (this.props.url && !nextProps.url) {
this.stop()
clearTimeout(this.updateTimeout)
} else if (!this.props.playing && nextProps.playing) {
this.play()
} else if (this.props.playing && !nextProps.playing) {
Expand Down Expand Up @@ -52,7 +53,8 @@ export default class Base extends Component {
}
onReady = () => {
this.setVolume(this.props.volume)
if (this.props.playing) {
if (this.props.playing || this.preloading) {
this.preloading = false
this.play()
}
}
Expand Down
9 changes: 5 additions & 4 deletions src/players/FilePlayer.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,18 @@ export default class FilePlayer extends Base {
this.player.onpause = this.props.onPause
this.player.onended = this.props.onEnded
this.player.onerror = this.props.onError
super.componentDidMount()
}
play (url) {
load (url) {
this.player.src = url
}
play () {
this.player.play()
}
pause () {
this.player.pause()
}
stop () {
// No need to stop
this.player.src = ''
}
seekTo (fraction) {
this.player.currentTime = this.player.duration * fraction
Expand All @@ -50,7 +52,6 @@ export default class FilePlayer extends Base {
return (
<Media
ref='player'
src={this.props.url}
style={style}
width={this.props.width}
height={this.props.height}
Expand Down
10 changes: 5 additions & 5 deletions src/players/SoundCloud.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,7 @@ export default class SoundCloud extends Base {
return fetch(RESOLVE_URL + '?url=' + url + '&client_id=' + this.props.soundcloudConfig.clientId)
.then(response => response.json())
}
play (url) {
if (!url && this.player) {
this.player.play()
return
}
load (url) {
this.stop()
this.getSDK().then(SC => {
this.getSongData(url).then(data => {
Expand Down Expand Up @@ -79,6 +75,10 @@ export default class SoundCloud extends Base {
onfinish: this.props.onFinish,
ondataerror: this.props.onError
}
play () {
if (!this.player) return
this.player.play()
}
pause () {
if (!this.player) return
this.player.pause()
Expand Down
26 changes: 16 additions & 10 deletions src/players/Vimeo.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import Base from './Base'
const IFRAME_SRC = 'https://player.vimeo.com/video/'
const MATCH_URL = /https?:\/\/(?:www\.|player\.)?vimeo.com\/(?:channels\/(?:\w+\/)?|groups\/([^\/]*)\/videos\/|album\/(\d+)\/video\/|video\/|)(\d+)(?:$|\/|\?)/
const MATCH_MESSAGE_ORIGIN = /^https?:\/\/player.vimeo.com/
const BLANK_VIDEO_URL = 'https://vimeo.com/127250231'
const DEFAULT_IFRAME_PARAMS = {
api: 1,
autoplay: 0,
Expand All @@ -25,19 +26,24 @@ export default class Vimeo extends Base {
componentDidMount () {
window.addEventListener('message', this.onMessage, false)
this.iframe = this.refs.iframe

if (!this.props.url && this.props.vimeoConfig.preload) {
this.preloading = true
this.load(BLANK_VIDEO_URL)
}

super.componentDidMount()
}
play (url) {
if (url) {
const id = url.match(MATCH_URL)[3]
const iframeParams = {
...DEFAULT_IFRAME_PARAMS,
...this.props.vimeoConfig.iframeParams
}
this.iframe.src = IFRAME_SRC + id + '?' + stringify(iframeParams)
} else {
this.postMessage('play')
load (url) {
const id = url.match(MATCH_URL)[3]
const iframeParams = {
...DEFAULT_IFRAME_PARAMS,
...this.props.vimeoConfig.iframeParams
}
this.iframe.src = IFRAME_SRC + id + '?' + stringify(iframeParams)
}
play () {
this.postMessage('play')
}
pause () {
this.postMessage('pause')
Expand Down
19 changes: 16 additions & 3 deletions src/players/YouTube.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const SDK_URL = '//www.youtube.com/iframe_api'
const SDK_GLOBAL = 'YT'
const MATCH_URL = /^(?:https?:\/\/)?(?:www\.)?(?:youtu\.be\/|youtube\.com\/(?:embed\/|v\/|watch\?v=|watch\?.+&v=))((\w|-){11})(?:\S+)?$/
const PLAYER_ID = 'youtube-player'
const BLANK_VIDEO_URL = 'https://www.youtube.com/watch?v=GlCmAC4MHek'
const DEFAULT_PLAYER_VARS = {
autoplay: 0,
controls: 0,
Expand All @@ -20,6 +21,13 @@ export default class YouTube extends Base {
static canPlay (url) {
return MATCH_URL.test(url)
}
componentDidMount () {
if (!this.props.url && this.props.youtubeConfig.preload) {
this.preloading = true
this.load(BLANK_VIDEO_URL)
}
super.componentDidMount()
}
getSDK () {
if (window[SDK_GLOBAL]) {
return Promise.resolve(window[SDK_GLOBAL])
Expand All @@ -33,13 +41,14 @@ export default class YouTube extends Base {
})
})
}
play (url) {
load (url, playing) {
const id = url && url.match(MATCH_URL)[1]
if (this.player) {
if (id) {
this.stop()
if (playing) {
this.player.loadVideoById(id)
} else {
this.player.playVideo()
this.player.cueVideoById(id)
}
return
}
Expand All @@ -64,6 +73,10 @@ export default class YouTube extends Base {
if (state.data === YT.PlayerState.BUFFERING) this.props.onBuffer()
if (state.data === YT.PlayerState.ENDED) this.props.onEnded()
}
play () {
if (!this.player) return
this.player.playVideo()
}
pause () {
if (!this.player) return
this.player.pauseVideo()
Expand Down
6 changes: 4 additions & 2 deletions src/props.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,12 @@ export const defaultProps = {
clientId: 'e8b6f84fbcad14c301ca1355cae1dea2'
},
youtubeConfig: {
playerVars: {}
playerVars: {},
preload: false
},
vimeoConfig: {
iframeParams: {}
iframeParams: {},
preload: false
},
onPlay: function () {},
onPause: function () {},
Expand Down

0 comments on commit 31b7d3d

Please sign in to comment.