|
1 | 1 | import React from 'react' |
2 | 2 |
|
3 | 3 | import Base from './Base' |
| 4 | +import loadScript from 'load-script' |
4 | 5 |
|
5 | 6 | const AUDIO_EXTENSIONS = /\.(m4a|mp4a|mpga|mp2|mp2a|mp3|m2a|m3a|wav|weba|aac|oga|spx)($|\?)/i |
| 7 | +const HLS_EXTENSIONS = /\.(m3u8)($|\?)/i |
| 8 | +const HLS_SDK_URL = 'https://cdn.jsdelivr.net/hls.js/latest/hls.min.js' |
| 9 | +const HLS_GLOBAL = 'Hls' |
| 10 | +const DASH_EXTENSIONS = /\.(mpd)($|\?)/i |
| 11 | +const DASH_SDK_URL = 'https://cdnjs.cloudflare.com/ajax/libs/dashjs/2.5.0/dash.all.min.js' |
| 12 | +const DASH_GLOBAL = 'dashjs' |
6 | 13 |
|
7 | 14 | export default class FilePlayer extends Base { |
8 | 15 | static displayName = 'FilePlayer' |
@@ -35,8 +42,26 @@ export default class FilePlayer extends Base { |
35 | 42 | this.player.removeEventListener('error', onError) |
36 | 43 | super.componentWillUnmount() |
37 | 44 | } |
38 | | - load () { |
39 | | - // Setting the src is handled by render |
| 45 | + shouldUseHLS (url) { |
| 46 | + return HLS_EXTENSIONS.test(url) || this.props.fileConfig.forceHLS |
| 47 | + } |
| 48 | + shouldUseDASH (url) { |
| 49 | + return DASH_EXTENSIONS.test(url) || this.props.fileConfig.forceDASH |
| 50 | + } |
| 51 | + load (url) { |
| 52 | + if (this.shouldUseHLS(url)) { |
| 53 | + loadSDK(HLS_SDK_URL, HLS_GLOBAL).then(Hls => { |
| 54 | + const hls = new Hls() |
| 55 | + hls.loadSource(url) |
| 56 | + hls.attachMedia(this.player) |
| 57 | + }) |
| 58 | + } |
| 59 | + if (this.shouldUseDASH(url)) { |
| 60 | + loadSDK(DASH_SDK_URL, DASH_GLOBAL).then(dashjs => { |
| 61 | + const player = dashjs.MediaPlayer().create() |
| 62 | + player.initialize(this.player, url, true) |
| 63 | + }) |
| 64 | + } |
40 | 65 | } |
41 | 66 | play () { |
42 | 67 | this.player.play() |
@@ -79,34 +104,46 @@ export default class FilePlayer extends Base { |
79 | 104 | const { src, type } = source |
80 | 105 | return <source key={src} src={src} type={type} /> |
81 | 106 | } |
82 | | - renderSources = url => { |
83 | | - if (url instanceof Array === false) { |
84 | | - return null |
85 | | - } |
86 | | - return url.map(this.renderSource) |
87 | | - } |
88 | 107 | ref = player => { |
89 | 108 | this.player = player |
90 | 109 | } |
91 | 110 | render () { |
92 | 111 | const { url, loop, controls, fileConfig } = this.props |
93 | | - const Media = AUDIO_EXTENSIONS.test(url) || fileConfig.forceAudio ? 'audio' : 'video' |
| 112 | + const useAudio = AUDIO_EXTENSIONS.test(url) || fileConfig.forceAudio |
| 113 | + const useHLS = this.shouldUseHLS(url) |
| 114 | + const useDASH = this.shouldUseDASH(url) |
| 115 | + const Element = useAudio ? 'audio' : 'video' |
| 116 | + const src = url instanceof Array || useHLS || useDASH ? undefined : url |
94 | 117 | const style = { |
95 | 118 | width: '100%', |
96 | 119 | height: '100%', |
97 | 120 | display: url ? 'block' : 'none' |
98 | 121 | } |
99 | 122 | return ( |
100 | | - <Media |
| 123 | + <Element |
101 | 124 | ref={this.ref} |
102 | | - src={url instanceof Array ? undefined : url} |
| 125 | + src={src} |
103 | 126 | style={style} |
104 | 127 | preload='auto' |
105 | 128 | controls={controls} |
106 | 129 | loop={loop} |
107 | 130 | {...fileConfig.attributes}> |
108 | | - {this.renderSources(url)} |
109 | | - </Media> |
| 131 | + {url instanceof Array && |
| 132 | + url.map(this.renderSource) |
| 133 | + } |
| 134 | + </Element> |
110 | 135 | ) |
111 | 136 | } |
112 | 137 | } |
| 138 | + |
| 139 | +function loadSDK (url, globalVar) { |
| 140 | + if (window[globalVar]) { |
| 141 | + return Promise.resolve(window[globalVar]) |
| 142 | + } |
| 143 | + return new Promise((resolve, reject) => { |
| 144 | + loadScript(url, err => { |
| 145 | + if (err) reject(err) |
| 146 | + resolve(window[globalVar]) |
| 147 | + }) |
| 148 | + }) |
| 149 | +} |
0 commit comments