@@ -10,6 +10,7 @@ export default class MSE {
10
10
constructor ( video , src ) {
11
11
this . video = video
12
12
this . src = src
13
+ this . qualityChangeFlag = false
13
14
this . videoQueue = [ ]
14
15
this . audioQueue = [ ]
15
16
this . sourceBuffers = {
@@ -67,7 +68,7 @@ export default class MSE {
67
68
68
69
init ( ) {
69
70
// 获取 mdat 外的数据
70
- this . loadData ( )
71
+ return this . loadData ( )
71
72
. then ( res => {
72
73
return new MP4Parse ( new Uint8Array ( res ) ) . mp4BoxTreeObject
73
74
} )
@@ -116,10 +117,17 @@ export default class MSE {
116
117
FMP4 . moov ( this . mp4Probe . mp4Data , 'audio' )
117
118
)
118
119
119
- this . mediaSource . addEventListener ( 'sourceopen' , ( ) => {
120
+ // 如果是切换清晰度,mediaSource 的 readyState 已经 open 了,可以直接 append 数据。
121
+ // mediaSource is already open when we switch video quality.
122
+ if ( this . qualityChangeFlag ) {
120
123
this . handleAppendBuffer ( videoRawData , 'video' )
121
124
this . handleAppendBuffer ( audioRawData , 'audio' )
122
- } )
125
+ } else {
126
+ this . mediaSource . addEventListener ( 'sourceopen' , ( ) => {
127
+ this . handleAppendBuffer ( videoRawData , 'video' )
128
+ this . handleAppendBuffer ( audioRawData , 'audio' )
129
+ } )
130
+ }
123
131
} )
124
132
}
125
133
@@ -144,10 +152,13 @@ export default class MSE {
144
152
145
153
// 对于已经请求的数据不再重复请求
146
154
// No need to repeat request video data
147
- if ( time && this . hasBufferedCache ( this . video . currentTime ) ) {
155
+ if (
156
+ time &&
157
+ this . hasBufferedCache ( this . video . currentTime ) &&
158
+ ! this . qualityChangeFlag
159
+ ) {
148
160
return
149
161
}
150
-
151
162
this . handleReplayCase ( )
152
163
153
164
this . loadData ( start , end ) . then ( mdatBuffer => {
@@ -180,9 +191,30 @@ export default class MSE {
180
191
if ( time ) {
181
192
this . needUpdateTime = true
182
193
}
194
+
195
+ this . qualityChangeFlag = false
183
196
} )
184
197
}
185
198
199
+ changeQuality ( newSrc ) {
200
+ this . src = newSrc
201
+ this . qualityChangeFlag = true
202
+ this . removeBuffer ( )
203
+
204
+ this . init ( ) . then ( ( ) => {
205
+ this . video . currentTime = this . video . currentTime
206
+ } )
207
+ }
208
+
209
+ removeBuffer ( ) {
210
+ for ( const key in this . sourceBuffers ) {
211
+ const track = this . sourceBuffers [ key ]
212
+ const length = track . buffered . length
213
+
214
+ track . remove ( track . buffered . start ( 0 ) , track . buffered . end ( length - 1 ) )
215
+ }
216
+ }
217
+
186
218
loadData ( start = 0 , end = MAGIC_NUMBER ) {
187
219
return new Promise ( resolve => {
188
220
new FragmentFetch ( this . src , start , end , resolve )
0 commit comments