diff --git a/src/demo/App.js b/src/demo/App.js index de6ce80d..6662879b 100644 --- a/src/demo/App.js +++ b/src/demo/App.js @@ -347,6 +347,12 @@ class App extends Component { {this.renderLoadButton('https://video.vidyard.com/watch/BLXgYCDGfwU62vdMWybNVJ', 'Test B')} + + Cloudflare Stream + + {this.renderLoadButton('https://watch.cloudflarestream.com/5d5bc37ffcf54c9b82e996823bffbb81', 'Test A')} + + Files diff --git a/src/patterns.js b/src/patterns.js index 3aafc540..2e225ce7 100644 --- a/src/patterns.js +++ b/src/patterns.js @@ -11,6 +11,7 @@ export const MATCH_URL_TWITCH_CHANNEL = /(?:www\.|go\.)?twitch\.tv\/([a-zA-Z0-9_ export const MATCH_URL_DAILYMOTION = /^(?:(?:https?):)?(?:\/\/)?(?:www\.)?(?:(?:dailymotion\.com(?:\/embed)?\/video)|dai\.ly)\/([a-zA-Z0-9]+)(?:_[\w_-]+)?$/ export const MATCH_URL_MIXCLOUD = /mixcloud\.com\/([^/]+\/[^/]+)/ export const MATCH_URL_VIDYARD = /vidyard.com\/(?:watch\/)?([a-zA-Z0-9-]+)/ +export const MATCH_URL_CLOUDFLARESTREAM = /watch.cloudflarestream\.com\/.+/ export const AUDIO_EXTENSIONS = /\.(m4a|mp4a|mpga|mp2|mp2a|mp3|m2a|m3a|wav|weba|aac|oga|spx)($|\?)/i export const VIDEO_EXTENSIONS = /\.(mp4|og[gv]|webm|mov|m4v)($|\?)/i export const HLS_EXTENSIONS = /\.(m3u8)($|\?)/i @@ -55,5 +56,6 @@ export const canPlay = { dailymotion: url => MATCH_URL_DAILYMOTION.test(url), mixcloud: url => MATCH_URL_MIXCLOUD.test(url), vidyard: url => MATCH_URL_VIDYARD.test(url), + cloudflareStream: url => MATCH_URL_CLOUDFLARESTREAM.test(url), file: canPlayFile } diff --git a/src/players/CloudflareStream.js b/src/players/CloudflareStream.js new file mode 100644 index 00000000..531e7329 --- /dev/null +++ b/src/players/CloudflareStream.js @@ -0,0 +1,135 @@ +import React, { Component } from 'react' + +import { callPlayer } from '../utils' +import { canPlay, MATCH_URL_CLOUDFLARESTREAM } from '../patterns' + +export default class CloudflareStream extends Component { + static displayName = 'CloudFlare' + static canPlay = canPlay.cloudflare + callPlayer = callPlayer + + componentDidMount () { + this.props.onMount && this.props.onMount(this) + } + + componentDidUpdate () { + if (this.props.playing) { + this.play() + } else { + this.pause() + } + } + + componentWillUnmount () { + document.body.removeChild(this.script) + } + + load (url) { + console.log('Cloudflarestream player loaded') + + if (MATCH_URL_CLOUDFLARESTREAM.test(url)) { + this.props.onReady() + + const src = url.substring(url.lastIndexOf('/') + 1) + this.script = document.createElement('script') + this.script.src = `https://embed.cloudflarestream.com/embed/r4xu.fla9.latest.js?video=${src}` + this.script['data-cfasync'] = 'false' + this.script.defer = true + this.script.type = 'text/javascript' + document.body.appendChild(this.script) + + this.player = document.getElementById('cloudflareStreamPlayer') + } else { + this.props.onError('Cloudflare player needs to take a Cloudflare Stream URL') + } + } + + refreshDuration () { + this.player.getDuration().then(duration => { + this.duration = duration + }) + } + + play () { + this.callPlayer('play') + } + + pause () { + this.callPlayer('pause') + } + + stop () { + this.callPlayer('unload') + } + + seekTo (seconds) { + if (this.player) { + this.player.currentTime = seconds + } + } + + setVolume (fraction) { + if (this.player) { + this.player.volume = fraction + } + } + + setLoop (loop) { + if (this.player) { + this.player.loop = loop + } + } + + setPlaybackRate (rate) { + this.callPlayer('setPlaybackRate', rate) + } + + mute = () => { + this.player.muted = true + } + + unmute = () => { + if (this.props.volume !== null) { + this.setVolume(this.props.volume) + this.player.muted = false + } + } + + getDuration () { + return this.player && this.player.duration + } + + getCurrentTime () { + return this.player && this.player.currentTime + } + + getSecondsLoaded () { + console.log('getSecondsLoaded returns current time because Cloudflare does not have a loaded property') + return this.player && this.player.currentTime + } + + ref = container => { + this.container = container + } + + render () { + const { display, url, muted } = this.props + + const src = url.substring(url.lastIndexOf('/') + 1) + const style = { + width: '100%', + height: '100%', + overflow: 'hidden', + display + } + return ( +
+ +
+ ) + } +} diff --git a/src/players/index.js b/src/players/index.js index 15c725c2..5c5cab9a 100644 --- a/src/players/index.js +++ b/src/players/index.js @@ -63,6 +63,12 @@ export default [ canPlay: canPlay.vidyard, lazyPlayer: lazy(() => import(/* webpackChunkName: 'reactPlayerVidyard' */'./Vidyard')) }, + { + key: 'cloudflareStream', + name: 'Cloudflare Stream', + canPlay: canPlay.cloudflareStream, + lazyPlayer: lazy(() => import(/* webpackChunkName: 'reactPlayerCloudflareStream' */'./CloudflareStream')) + }, { key: 'file', name: 'FilePlayer',