diff --git a/README.md b/README.md index f2130e5..6325119 100644 --- a/README.md +++ b/README.md @@ -54,6 +54,10 @@ For platforms like [Meteor](https://www.meteor.com) without direct use of `npm` * If you are using `npm` and need to support [browsers without `Promise`](http://caniuse.com/#feat=promises) you will need a [`Promise` polyfill](https://github.com/stefanpenner/es6-promise). * To support IE11 you will need to use [`babel-polyfill`](https://babeljs.io/docs/usage/polyfill) or a similar ES2015+ polyfill. +#### Autoplay + +As of Chrome 66, [videos must be `muted` in order to play automatically](https://www.theverge.com/2018/3/22/17150870/google-chrome-autoplay-videos-sound-mute-update). Some players, like Facebook, cannot be unmuted until the user interacts with the video, so you may want to enable `controls` to allow users to unmute videos themselves. + ### Props Prop | Description | Default diff --git a/src/Player.js b/src/Player.js index 821e7a3..748c464 100644 --- a/src/Player.js +++ b/src/Player.js @@ -42,12 +42,18 @@ export default class Player extends Component { if (playing && !nextProps.playing && this.isPlaying) { this.player.pause() } - if (nextProps.volume !== null) { - if (volume !== nextProps.volume && !nextProps.muted) { - this.player.setVolume(nextProps.volume) - } - if (muted !== nextProps.muted) { - this.player.setVolume(nextProps.muted ? 0 : nextProps.volume) + if (volume !== nextProps.volume && nextProps.volume !== null) { + this.player.setVolume(nextProps.volume) + } + if (muted !== nextProps.muted) { + if (nextProps.muted) { + this.player.mute() + } else { + this.player.unmute() + if (nextProps.volume !== null) { + // Set volume next tick to fix a bug with DailyMotion + setTimeout(() => this.player.setVolume(nextProps.volume)) + } } } if (playbackRate !== nextProps.playbackRate && this.player.setPlaybackRate) { @@ -121,8 +127,8 @@ export default class Player extends Component { this.isLoading = false const { onReady, playing, volume, muted } = this.props onReady() - if (muted || volume !== null) { - this.player.setVolume(muted ? 0 : volume) + if (!muted && volume !== null) { + this.player.setVolume(volume) } if (playing) { this.player.play() diff --git a/src/players/DailyMotion.js b/src/players/DailyMotion.js index f25e62f..3b6ddfa 100644 --- a/src/players/DailyMotion.js +++ b/src/players/DailyMotion.js @@ -38,6 +38,7 @@ export class DailyMotion extends Component { params: { controls: controls, autoplay: this.props.playing, + mute: this.props.muted, start: parseStartTime(url), origin: window.location.origin, ...config.dailymotion.params @@ -74,6 +75,12 @@ export class DailyMotion extends Component { setVolume (fraction) { this.callPlayer('setVolume', fraction) } + mute = () => { + this.callPlayer('setMuted', true) + } + unmute = () => { + this.callPlayer('setMuted', false) + } getDuration () { return this.player.duration || null } diff --git a/src/players/Facebook.js b/src/players/Facebook.js index 0c19a98..aa961da 100644 --- a/src/players/Facebook.js +++ b/src/players/Facebook.js @@ -35,7 +35,10 @@ export class Facebook extends Component { this.player.subscribe('finishedPlaying', this.props.onEnded) this.player.subscribe('startedBuffering', this.props.onBuffer) this.player.subscribe('error', this.props.onError) - this.callPlayer('unmute') + if (!this.props.muted) { + // Player is muted by default + this.callPlayer('unmute') + } this.props.onReady() } }) @@ -54,11 +57,14 @@ export class Facebook extends Component { this.callPlayer('seek', seconds) } setVolume (fraction) { - if (fraction !== 0) { - this.callPlayer('unmute') - } this.callPlayer('setVolume', fraction) } + mute = () => { + this.callPlayer('mute') + } + unmute = () => { + this.callPlayer('unmute') + } getDuration () { return this.callPlayer('getDuration') } @@ -80,8 +86,9 @@ export class Facebook extends Component { id={this.playerID} className='fb-video' data-href={this.props.url} + data-autoplay={this.props.playing ? 'true' : 'false'} data-allowfullscreen='true' - data-controls={!this.props.controls ? 'false' : undefined} + data-controls={this.props.controls ? 'true' : 'false'} /> ) } diff --git a/src/players/FilePlayer.js b/src/players/FilePlayer.js index f60c66d..559ecaf 100644 --- a/src/players/FilePlayer.js +++ b/src/players/FilePlayer.js @@ -140,6 +140,12 @@ export class FilePlayer extends Component { setVolume (fraction) { this.player.volume = fraction } + mute = () => { + this.player.muted = true + } + unmute = () => { + this.player.muted = false + } setPlaybackRate (rate) { this.player.playbackRate = rate } @@ -185,12 +191,12 @@ export class FilePlayer extends Component { this.player = player } render () { - const { url, loop, controls, config, width, height } = this.props + const { url, playing, loop, controls, muted, config, width, height } = this.props const useAudio = this.shouldUseAudio(this.props) const Element = useAudio ? 'audio' : 'video' const style = { - width: !width || width === 'auto' ? width : '100%', - height: !height || height === 'auto' ? height : '100%' + width: width === 'auto' ? width : '100%', + height: height === 'auto' ? height : '100%' } return ( {url instanceof Array && diff --git a/src/players/Mixcloud.js b/src/players/Mixcloud.js index 2ea9d47..0e2a70d 100644 --- a/src/players/Mixcloud.js +++ b/src/players/Mixcloud.js @@ -46,6 +46,12 @@ export class Mixcloud extends Component { setVolume (fraction) { // No volume support } + mute = () => { + // No volume support + } + unmute = () => { + // No volume support + } getDuration () { return this.duration } diff --git a/src/players/SoundCloud.js b/src/players/SoundCloud.js index 8207414..39d4948 100644 --- a/src/players/SoundCloud.js +++ b/src/players/SoundCloud.js @@ -57,6 +57,14 @@ export class SoundCloud extends Component { setVolume (fraction) { this.callPlayer('setVolume', fraction * 100) } + mute = () => { + this.setVolume(0) + } + unmute = () => { + if (this.props.volume !== null) { + this.setVolume(this.props.volume) + } + } getDuration () { return this.duration } diff --git a/src/players/Streamable.js b/src/players/Streamable.js index 3898bf4..295afdb 100644 --- a/src/players/Streamable.js +++ b/src/players/Streamable.js @@ -35,6 +35,9 @@ export class Streamable extends Component { this.secondsLoaded = this.duration * percent } }) + if (this.props.muted) { + this.player.mute() + } }, this.props.onError) } play () { @@ -52,6 +55,12 @@ export class Streamable extends Component { setVolume (fraction) { this.callPlayer('setVolume', fraction * 100) } + mute = () => { + this.callPlayer('mute') + } + unmute = () => { + this.callPlayer('unmute') + } getDuration () { return this.duration } diff --git a/src/players/Twitch.js b/src/players/Twitch.js index 3fd35e2..d384a9d 100644 --- a/src/players/Twitch.js +++ b/src/players/Twitch.js @@ -36,6 +36,7 @@ export class Twitch extends Component { width: '100%', playsinline: playsinline, autoplay: this.props.playing, + muted: this.props.muted, ...config.twitch.options }) const { READY, PLAY, PAUSE, ENDED } = Twitch.Player @@ -60,6 +61,12 @@ export class Twitch extends Component { setVolume (fraction) { this.callPlayer('setVolume', fraction) } + mute = () => { + this.callPlayer('setMuted', true) + } + unmute = () => { + this.callPlayer('setMuted', false) + } getDuration () { return this.callPlayer('getDuration') } diff --git a/src/players/Vimeo.js b/src/players/Vimeo.js index 5c9e670..0030eec 100644 --- a/src/players/Vimeo.js +++ b/src/players/Vimeo.js @@ -28,6 +28,8 @@ export class Vimeo extends Component { this.player = new Vimeo.Player(this.container, { ...this.props.config.vimeo.playerOptions, url, + autoplay: this.props.playing, + muted: this.props.muted, loop: this.props.loop }) this.player.ready().then(() => { @@ -69,6 +71,14 @@ export class Vimeo extends Component { setVolume (fraction) { this.callPlayer('setVolume', fraction) } + mute = () => { + this.setVolume(0) + } + unmute = () => { + if (this.props.volume !== null) { + this.setVolume(this.props.volume) + } + } getDuration () { return this.duration } diff --git a/src/players/Wistia.js b/src/players/Wistia.js index c3b3503..cb1b516 100644 --- a/src/players/Wistia.js +++ b/src/players/Wistia.js @@ -17,12 +17,15 @@ export class Wistia extends Component { return url && url.match(MATCH_URL)[1] } load (url) { - const { controls, onReady, onPlay, onPause, onSeek, onEnded, config } = this.props + const { playing, muted, controls, onReady, onPlay, onPause, onSeek, onEnded, config } = this.props getSDK(SDK_URL, SDK_GLOBAL).then(() => { window._wq = window._wq || [] window._wq.push({ id: this.getID(url), options: { + autoPlay: playing, + silentAutoPlay: 'allow', + muted: muted, controlsVisibleOnLoad: controls, ...config.wistia.options }, @@ -52,6 +55,12 @@ export class Wistia extends Component { setVolume (fraction) { this.callPlayer('volume', fraction) } + mute = () => { + this.callPlayer('mute') + } + unmute = () => { + this.callPlayer('unmute') + } setPlaybackRate (rate) { this.callPlayer('playbackRate', rate) } diff --git a/src/players/YouTube.js b/src/players/YouTube.js index 47a5b4c..9e40b21 100644 --- a/src/players/YouTube.js +++ b/src/players/YouTube.js @@ -15,7 +15,7 @@ export class YouTube extends Component { callPlayer = callPlayer load (url, isReady) { - const { playsinline, controls, config, onError } = this.props + const { playing, muted, playsinline, controls, config, onError } = this.props const id = url && url.match(MATCH_URL)[1] if (isReady) { this.player.cueVideoById({ @@ -31,6 +31,8 @@ export class YouTube extends Component { height: '100%', videoId: id, playerVars: { + autoplay: playing ? 1 : 0, + mute: muted ? 1 : 0, controls: controls ? 1 : 0, start: parseStartTime(url), origin: window.location.origin, @@ -70,6 +72,12 @@ export class YouTube extends Component { setVolume (fraction) { this.callPlayer('setVolume', fraction * 100) } + mute = () => { + this.callPlayer('mute') + } + unmute = () => { + this.callPlayer('unMute') + } setPlaybackRate (rate) { this.callPlayer('setPlaybackRate', rate) } diff --git a/src/props.js b/src/props.js index d3509b3..b3253f2 100644 --- a/src/props.js +++ b/src/props.js @@ -93,7 +93,6 @@ export const defaultProps = { }, youtube: { playerVars: { - autoplay: 0, playsinline: 1, showinfo: 0, rel: 0, @@ -115,7 +114,6 @@ export const defaultProps = { vimeo: { playerOptions: { autopause: false, - autoplay: false, byline: false, portrait: false, title: false