diff --git a/CHANGELOG.md b/CHANGELOG.md
index 13fe1e89..2e75e6da 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -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)
diff --git a/README.md b/README.md
index 25f63b2f..1a4e2d49 100644
--- a/README.md
+++ b/README.md
@@ -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
diff --git a/src/ReactPlayer.js b/src/ReactPlayer.js
index 20bd9223..489708f3 100644
--- a/src/ReactPlayer.js
+++ b/src/ReactPlayer.js
@@ -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
+ const { youtubeConfig, soundcloudConfig, vimeoConfig, ...activeProps } = this.props
+ const props = active ? { ...activeProps, ref: 'player' } : {}
+ return (
+
+ )
}
render () {
const style = {
diff --git a/src/players/Base.js b/src/players/Base.js
index b1ff9a2a..545ce900 100644
--- a/src/players/Base.js
+++ b/src/players/Base.js
@@ -9,6 +9,9 @@ export default class Base extends Component {
static defaultProps = defaultProps
componentDidMount () {
this.update()
+ if (this.props.url) {
+ this.load(this.props.url)
+ }
}
componentWillUnmount () {
this.stop()
@@ -16,14 +19,12 @@ export default class Base extends Component {
}
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) {
@@ -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()
}
}
diff --git a/src/players/FilePlayer.js b/src/players/FilePlayer.js
index 49b7c582..3f0a11d5 100644
--- a/src/players/FilePlayer.js
+++ b/src/players/FilePlayer.js
@@ -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
@@ -50,7 +52,6 @@ export default class FilePlayer extends Base {
return (
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 => {
@@ -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()
diff --git a/src/players/Vimeo.js b/src/players/Vimeo.js
index a5b8c83d..9daa3e0e 100644
--- a/src/players/Vimeo.js
+++ b/src/players/Vimeo.js
@@ -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,
@@ -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')
diff --git a/src/players/YouTube.js b/src/players/YouTube.js
index f0bbf924..49c24de0 100644
--- a/src/players/YouTube.js
+++ b/src/players/YouTube.js
@@ -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,
@@ -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])
@@ -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
}
@@ -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()
diff --git a/src/props.js b/src/props.js
index 9afa2951..4d2f12f0 100644
--- a/src/props.js
+++ b/src/props.js
@@ -31,10 +31,12 @@ export const defaultProps = {
clientId: 'e8b6f84fbcad14c301ca1355cae1dea2'
},
youtubeConfig: {
- playerVars: {}
+ playerVars: {},
+ preload: false
},
vimeoConfig: {
- iframeParams: {}
+ iframeParams: {},
+ preload: false
},
onPlay: function () {},
onPause: function () {},