Skip to content

Commit

Permalink
Added DailyMotion support.
Browse files Browse the repository at this point in the history
  • Loading branch information
tarhan authored and cookpete committed Apr 27, 2017
1 parent e86d7b8 commit 71dcda6
Show file tree
Hide file tree
Showing 5 changed files with 190 additions and 2 deletions.
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ ReactPlayer
[![Dependency Status](https://img.shields.io/david/CookPete/react-player.svg)](https://david-dm.org/CookPete/react-player)
[![devDependency Status](https://img.shields.io/david/dev/CookPete/react-player.svg)](https://david-dm.org/CookPete/react-player?type=dev)

A react component for playing a variety of URLs, including file paths, YouTube, SoundCloud, Streamable, Vidme, Vimeo and Wistia. Used by [rplayr](http://rplayr.com), an app to generate playlists from Reddit URLs.
A react component for playing a variety of URLs, including file paths, YouTube, SoundCloud, Streamable, Vidme, Vimeo, Wistia and DailyMotion. Used by [rplayr](http://rplayr.com), an app to generate playlists from Reddit URLs.

The component parses a URL and loads in the appropriate markup and external SDKs to play media from [various sources](#supported-media). [Props](#props) can be passed in to control playback and react to events such as buffering or media ending.

Expand Down Expand Up @@ -113,12 +113,13 @@ Prop | Description
`vimeoConfig` | Configuration object for the Vimeo player.<br />Set `iframeParams` to override the [default params](https://developer.vimeo.com/player/embedding#universal-parameters).<br />Set `preload` for [preloading](#preloading).
`youtubeConfig` | Configuration object for the YouTube player.<br />Set `playerVars` to override the [default player vars](https://developers.google.com/youtube/player_parameters?playerVersion=HTML5).<br />Set `preload` for [preloading](#preloading).
`vidmeConfig` | Configuration object for the Vidme player.<br />Set `format` to use a certain quality of video, when available.<br />Possible values: `240p`, `480p`, `720p`, `1080p`, `dash`, `hls`
`dailymotionConfig` | Configuration object for the DailyMotion player.<br />Set `params` to override the [default player vars](https://developer.dailymotion.com/player#player-parameters).<br />Set `preload` for [preloading](#preloading).
`fileConfig` | Configuration object for the file player.<br />Set `attributes` to apply [element attributes](https://developer.mozilla.org/en/docs/Web/HTML/Element/video#Attributes).
`facebookConfig` | Configuration object for the Facebook player.<br />Set `appId` to your own [Facebook app ID](https://developers.facebook.com/docs/apps/register#app-id).

##### 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.
Both `youtubeConfig`, `vimeoConfig`, `dailymotionConfig` 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 All @@ -138,6 +139,7 @@ Prop | Description
* Vidme videos are [resolved](https://docs.vid.me/#api-Video-DetailByURL) and played in a [`<video>`](https://developer.mozilla.org/en/docs/Web/HTML/Element/video) element using the track’s `complete_url` path
* Vimeo videos use the [Vimeo Player API](https://developer.vimeo.com/player/js-api)
* Wistia videos use the [Wistia Player API](https://wistia.com/doc/player-api)
* DailyMotion videos use the [DailyMotion Player API](https://developer.dailymotion.com/player)
* [Supported file types](https://github.com/CookPete/react-player/blob/master/src/players/FilePlayer.js#L5-L6) are playing using [`<video>`](https://developer.mozilla.org/en/docs/Web/HTML/Element/video) or [`<audio>`](https://developer.mozilla.org/en/docs/Web/HTML/Element/audio) elements

### Contributing
Expand Down
3 changes: 3 additions & 0 deletions src/ReactPlayer.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import FilePlayer from './players/FilePlayer'
import Streamable from './players/Streamable'
import Vidme from './players/Vidme'
import Wistia from './players/Wistia'
import DailyMotion from './players/DailyMotion'

export default class ReactPlayer extends Component {
static displayName = 'ReactPlayer'
Expand Down Expand Up @@ -88,6 +89,8 @@ export default class ReactPlayer extends Component {
players.push(Vimeo)
} else if (Facebook.canPlay(url)) {
players.push(Facebook)
} else if (DailyMotion.canPlay(url)) {
players.push(DailyMotion)
} else if (Streamable.canPlay(url)) {
players.push(Streamable)
} else if (Vidme.canPlay(url)) {
Expand Down
7 changes: 7 additions & 0 deletions src/demo/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,13 @@ export default class App extends Component {
{this.renderLoadButton('https://www.youtube.com/watch?v=jNgP6d9HraI', 'Test B')}
</td>
</tr>
<tr>
<th>DailyMotion</th>
<td>
{this.renderLoadButton('http://www.dailymotion.com/video/x522udb', 'Test A')}
{this.renderLoadButton('http://www.dailymotion.com/video/x2hzs96_feast-2015-oscar-winning-short-movie-full-length-hd_shortfilms', 'Test B')}
</td>
</tr>
<tr>
<th>SoundCloud</th>
<td>
Expand Down
168 changes: 168 additions & 0 deletions src/players/DailyMotion.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
import React from 'react'
import loadScript from 'load-script'

import Base from './Base'
import { parseStartTime } from '../utils'

const SDK_URL = 'https://api.dmcdn.net/all.js'
const SDK_GLOBAL = 'DM'
const SDK_GLOBAL_READY = 'dmAsyncInit'
const MATCH_URL = /^.+dailymotion.com\/(video|hub)\/([^_]+)[^#]*(#video=([^_&]+))?/
const BLANK_VIDEO_URL = 'http://www.dailymotion.com/video/x522udb'
const DEFAULT_PLAYER_VARS = {
autoplay: 0,
api: 1,
'endscreen-enable': false
}

export default class DailyMotion extends Base {
static displayName = 'DailyMotion'
static canPlay (url) {
return MATCH_URL.test(url)
}
componentDidMount () {
const { url, dailymotionConfig } = this.props
if (!url && dailymotionConfig.preload) {
this.preloading = true
this.load(BLANK_VIDEO_URL)
}
super.componentDidMount()
}
getSDK () {
if (window[SDK_GLOBAL] && window[SDK_GLOBAL].player) {
return Promise.resolve(window[SDK_GLOBAL])
}
return new Promise((resolve, reject) => {
const previousOnReady = window[SDK_GLOBAL_READY]
window[SDK_GLOBAL_READY] = function () {
if (previousOnReady) previousOnReady()
resolve(window[SDK_GLOBAL])
}
loadScript(SDK_URL, err => {
if (err) {
reject(err)
}
})
})
}

parseId (url) {
if (url) {
const m = url.match(MATCH_URL)
if (m !== null) {
if (m[4] !== undefined) {
return m[4]
}
return m[2]
}
}
return null
}

load (url) {
const { controls, dailymotionConfig, onError, playing } = this.props
const id = this.parseId(url)
if (this.isReady) {
this.player.load(id, {
start: parseStartTime(url),
autoplay: playing
})
return
}
if (this.loadingSDK) {
this.loadOnReady = url
return
}
this.loadingSDK = true
this.getSDK().then(DM => {
// eslint-disable-next-line new-cap
this.player = new DM.player(this.container, {
width: '100%',
height: '100%',
video: id,
params: {
...DEFAULT_PLAYER_VARS,
controls: controls,
autoplay: this.props.playing,
...dailymotionConfig.params,
start: parseStartTime(url),
origin: window.location.origin
},
events: {
apiready: () => {
this.loadingSDK = false
},
video_end: this.onEnded,
durationchange: this.onDurationChange,
pause: this.props.onPause,
playing: this.onPlay,
waiting: this.props.onBuffer,
loadedmetadata: this.onReady,
error: event => onError(event)
}
})
}, onError)
}
onDurationChange = (event) => {
const { onDuration } = this.props
const duration = this.getDuration()
onDuration(duration)
}

onEnded = () => {
const { loop, onEnded } = this.props
if (loop) {
this.seekTo(0)
}
onEnded()
}
play () {
if (!this.isReady || !this.player.play) return
this.player.play()
}
pause () {
if (!this.isReady || !this.player.pause) return
this.player.pause()
}
stop () {
if (!this.isReady || !this.player.pause) return
this.player.pause()
this.onEnded()
}
seekTo (fraction) {
super.seekTo(fraction)
if (!this.isReady || !this.player.seek) return
this.player.seek(this.getDuration() * fraction)
}
setVolume (fraction) {
if (!this.isReady || !this.player.setVolume) return
this.player.setVolume(fraction)
}
getDuration () {
if (!this.isReady || !this.player.duration) return null
return this.player.duration
}
getFractionPlayed () {
if (!this.isReady || !this.getDuration()) return null
return this.player.currentTime / this.getDuration()
}
getFractionLoaded () {
if (!this.isReady || !this.player.bufferedTime) return null
return this.player.bufferedTime
}
ref = container => {
this.container = container
}
render () {
const style = {
width: '100%',
height: '100%',
display: this.props.url ? 'block' : 'none'
}
return (
<div style={style}>
<div ref={this.ref} />
</div>
)
}
}
8 changes: 8 additions & 0 deletions src/props.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ export const propTypes = {
facebookConfig: shape({
appId: string
}),
dailymotionConfig: shape({
params: object,
preload: bool
}),
vimeoConfig: shape({
iframeParams: object,
preload: bool
Expand Down Expand Up @@ -68,6 +72,10 @@ export const defaultProps = {
facebookConfig: {
appId: '1309697205772819'
},
dailymotionConfig: {
params: {},
preload: false
},
vimeoConfig: {
iframeParams: {},
preload: false
Expand Down

0 comments on commit 71dcda6

Please sign in to comment.