Skip to content

Commit

Permalink
Add support for HLS and DASH streams
Browse files Browse the repository at this point in the history
Proper fix for #184
  • Loading branch information
cookpete committed May 9, 2017
1 parent 6f8da1f commit c28c7ff
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 20 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ Prop | Description
`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).<br />Set `forceAudio` to always render an `<audio>` element.
`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).<br />Set `forceAudio` to always render an `<audio>` element.<br />Set `forceHLS` to use [hls.js](https://github.com/video-dev/hls.js) for HLS streams.<br />Set `forceDASH` to always use [dash.js](https://github.com/Dash-Industry-Forum/dash.js) for DASH streams.
`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
Expand Down
8 changes: 5 additions & 3 deletions src/demo/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -226,10 +226,12 @@ export default class App extends Component {
<tr>
<th>Files</th>
<td>
{this.renderLoadButton('http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4', 'MP4')}
{this.renderLoadButton('http://clips.vorwaerts-gmbh.de/big_buck_bunny.ogv', 'OGV')}
{this.renderLoadButton('http://clips.vorwaerts-gmbh.de/big_buck_bunny.webm', 'WEBM')}
{this.renderLoadButton('http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4', 'mp4')}
{this.renderLoadButton('http://clips.vorwaerts-gmbh.de/big_buck_bunny.ogv', 'ogv')}
{this.renderLoadButton('http://clips.vorwaerts-gmbh.de/big_buck_bunny.webm', 'webm')}
{this.renderLoadButton(MULTIPLE_SOURCES, 'Multiple')}
{this.renderLoadButton('https://bitdash-a.akamaihd.net/content/MI201109210084_1/m3u8s/f08e80da-bf1d-4e3d-8899-f0f6155f6efa.m3u8', 'HLS (m3u8)')}
{this.renderLoadButton('http://dash.edgesuite.net/envivio/EnvivioDash3/manifest.mpd', 'DASH (mpd)')}
</td>
</tr>
<tr>
Expand Down
2 changes: 1 addition & 1 deletion src/demo/defaults.scss
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ textarea {
}

button {
margin-right: 5px;
margin: 3px;
padding: 6px 12px;
border: 0;
border-radius: 3px;
Expand Down
63 changes: 50 additions & 13 deletions src/players/FilePlayer.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
import React from 'react'

import Base from './Base'
import loadScript from 'load-script'

const AUDIO_EXTENSIONS = /\.(m4a|mp4a|mpga|mp2|mp2a|mp3|m2a|m3a|wav|weba|aac|oga|spx)($|\?)/i
const HLS_EXTENSIONS = /\.(m3u8)($|\?)/i
const HLS_SDK_URL = 'https://cdn.jsdelivr.net/hls.js/latest/hls.min.js'
const HLS_GLOBAL = 'Hls'
const DASH_EXTENSIONS = /\.(mpd)($|\?)/i
const DASH_SDK_URL = 'https://cdnjs.cloudflare.com/ajax/libs/dashjs/2.5.0/dash.all.min.js'
const DASH_GLOBAL = 'dashjs'

export default class FilePlayer extends Base {
static displayName = 'FilePlayer'
Expand Down Expand Up @@ -35,8 +42,26 @@ export default class FilePlayer extends Base {
this.player.removeEventListener('error', onError)
super.componentWillUnmount()
}
load () {
// Setting the src is handled by render
shouldUseHLS (url) {
return HLS_EXTENSIONS.test(url) || this.props.fileConfig.forceHLS
}
shouldUseDASH (url) {
return DASH_EXTENSIONS.test(url) || this.props.fileConfig.forceDASH
}
load (url) {
if (this.shouldUseHLS(url)) {
loadSDK(HLS_SDK_URL, HLS_GLOBAL).then(Hls => {
const hls = new Hls()
hls.loadSource(url)
hls.attachMedia(this.player)
})
}
if (this.shouldUseDASH(url)) {
loadSDK(DASH_SDK_URL, DASH_GLOBAL).then(dashjs => {
const player = dashjs.MediaPlayer().create()
player.initialize(this.player, url, true)
})
}
}
play () {
this.player.play()
Expand Down Expand Up @@ -79,34 +104,46 @@ export default class FilePlayer extends Base {
const { src, type } = source
return <source key={src} src={src} type={type} />
}
renderSources = url => {
if (url instanceof Array === false) {
return null
}
return url.map(this.renderSource)
}
ref = player => {
this.player = player
}
render () {
const { url, loop, controls, fileConfig } = this.props
const Media = AUDIO_EXTENSIONS.test(url) || fileConfig.forceAudio ? 'audio' : 'video'
const useAudio = AUDIO_EXTENSIONS.test(url) || fileConfig.forceAudio
const useHLS = this.shouldUseHLS(url)
const useDASH = this.shouldUseDASH(url)
const Element = useAudio ? 'audio' : 'video'
const src = url instanceof Array || useHLS || useDASH ? undefined : url
const style = {
width: '100%',
height: '100%',
display: url ? 'block' : 'none'
}
return (
<Media
<Element
ref={this.ref}
src={url instanceof Array ? undefined : url}
src={src}
style={style}
preload='auto'
controls={controls}
loop={loop}
{...fileConfig.attributes}>
{this.renderSources(url)}
</Media>
{url instanceof Array &&
url.map(this.renderSource)
}
</Element>
)
}
}

function loadSDK (url, globalVar) {
if (window[globalVar]) {
return Promise.resolve(window[globalVar])
}
return new Promise((resolve, reject) => {
loadScript(url, err => {
if (err) reject(err)
resolve(window[globalVar])
})
})
}
8 changes: 6 additions & 2 deletions src/props.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,9 @@ export const propTypes = {
}),
fileConfig: shape({
attributes: object,
forceAudio: bool
forceAudio: bool,
forceHLS: bool,
forceDASH: bool
}),
onReady: func,
onStart: func,
Expand Down Expand Up @@ -86,7 +88,9 @@ export const defaultProps = {
},
fileConfig: {
attributes: {},
forceAudio: false
forceAudio: false,
forceHLS: false,
forceDASH: false
},
onReady: function () {},
onStart: function () {},
Expand Down

0 comments on commit c28c7ff

Please sign in to comment.