@@ -3,30 +3,62 @@ import Hls from 'hls.js/dist/hls.light.min'
33import { getMasterM3U8Blob } from './utils'
44
55export default class Video extends Component {
6+ manuallyBuildAdaptiveM3U8Blob = false
67 hasLoadStarted = false
78
89 componentDidMount ( ) {
10+ const { src, sources, useAutoQuality} = this . props
911 this . hls = new Hls ( { autoStartLoad : false } )
1012 this . hls . attachMedia ( this . video )
11- const { sources} = this . props
12- const master = getMasterM3U8Blob ( sources )
13- this . src = URL . createObjectURL ( master )
13+
14+ const isAutoQualitySourceProvided = Boolean (
15+ sources . find ( s => s . quality === 'auto' )
16+ )
17+
18+ // 启用自动质量但是又没有提供 auto 规格的 source,那么就尝试本地手动生成
19+ if ( useAutoQuality && ! isAutoQualitySourceProvided ) {
20+ const master = getMasterM3U8Blob ( sources )
21+ this . src = URL . createObjectURL ( master )
22+ this . manuallyBuildAdaptiveM3U8Blob = true
23+ } else {
24+ this . src = src
25+ }
26+
1427 this . hls . loadSource ( this . src )
1528 }
1629
1730 componentDidUpdate ( prevProps ) {
1831 const { currentQuality, sources, paused} = this . props
32+
33+ // 切换清晰度
1934 if ( currentQuality !== prevProps . currentQuality ) {
20- const source = sources . find ( source => source . quality === currentQuality )
35+ const source = sources . find ( s => s . quality === currentQuality )
2136 if ( source ) {
22- const levels = this . hls . levels
23- const level = levels . findIndex ( item => item . url . includes ( source . source ) )
24- this . hls . nextLevel = level
37+ if ( this . manuallyBuildAdaptiveM3U8Blob ) {
38+ const levels = this . hls . levels
39+ const level = levels . findIndex ( l => l . url . includes ( source . source ) )
40+ this . hls . nextLevel = level
41+ } else {
42+ // TODO: 没有在 hls 的 API 内部找到顺畅切换 source 的方法
43+ // 因此这里比较直接和生硬
44+ const currentTime = this . video . currentTime
45+ this . hls . destroy ( )
46+ this . hls = new Hls ( { autoStartLoad : false } )
47+ this . hls . attachMedia ( this . video )
48+ this . hls . loadSource ( source . source )
49+ this . video . currentTime = currentTime
50+ this . hls . startLoad ( )
51+ if ( ! paused ) {
52+ this . video . play ( )
53+ }
54+ }
2555 } else {
56+ // 一定意味着选择了手动生成的「auto」
2657 this . hls . nextLevel = - 1
2758 }
2859 }
2960
61+ // 切换播放状态
3062 if ( ! paused && prevProps . paused && ! this . hasLoadStarted ) {
3163 this . hls . startLoad ( )
3264 this . hasLoadStarted = true
@@ -35,12 +67,23 @@ export default class Video extends Component {
3567
3668 componentWillUnmount ( ) {
3769 this . hls . destroy ( )
38- URL . revokeObjectURL ( this . src )
70+ if ( this . manuallyBuildAdaptiveM3U8Blob ) {
71+ URL . revokeObjectURL ( this . src )
72+ }
3973 }
4074
4175 render ( ) {
42- // eslint-disable-next-line no-unused-vars
43- const { onRef, currentQuality, src, sources, paused, ...props } = this . props
76+ const {
77+ onRef,
78+ /* eslint-disable no-unused-vars */
79+ currentQuality,
80+ useAutoQuality,
81+ src,
82+ sources,
83+ paused,
84+ /* eslint-enable no-unused-vars */
85+ ...props
86+ } = this . props
4487 return (
4588 < video
4689 ref = { el => {
0 commit comments