diff --git a/api-extractor/report/hls.js.api.md b/api-extractor/report/hls.js.api.md index 4a1d1129b69..0bbd6878405 100644 --- a/api-extractor/report/hls.js.api.md +++ b/api-extractor/report/hls.js.api.md @@ -459,7 +459,7 @@ export class BaseStreamController extends TaskLoop implements NetworkComponentAP // (undocumented) protected reduceLengthAndFlushBuffer(data: ErrorData): boolean; // (undocumented) - protected reduceMaxBufferLength(threshold: number): boolean; + protected reduceMaxBufferLength(threshold: number, fragDuration: number): boolean; // (undocumented) protected removeUnbufferedFrags(start?: number): void; // (undocumented) diff --git a/src/controller/base-stream-controller.ts b/src/controller/base-stream-controller.ts index 6a3674d9874..4d366db2d46 100644 --- a/src/controller/base-stream-controller.ts +++ b/src/controller/base-stream-controller.ts @@ -425,7 +425,7 @@ export default class BaseStreamController : 0; if ( backtracked === 1 || - this.reduceMaxBufferLength(minForwardBufferLength) + this.reduceMaxBufferLength(minForwardBufferLength, frag.duration) ) { fragmentTracker.removeFragment(frag); } @@ -1026,10 +1026,16 @@ export default class BaseStreamController return Math.min(maxBufLen, config.maxMaxBufferLength); } - protected reduceMaxBufferLength(threshold: number) { + protected reduceMaxBufferLength(threshold: number, fragDuration: number) { const config = this.config; - const minLength = threshold || config.maxBufferLength; - const reducedLength = config.maxMaxBufferLength / 2; + const minLength = Math.max( + Math.min(threshold, config.maxBufferLength), + fragDuration, + ); + const reducedLength = Math.max( + threshold - fragDuration * 3, + config.maxMaxBufferLength / 2, + ); if (reducedLength >= minLength) { // reduce max buffer length as it might be too high. we do this to avoid loop flushing ... config.maxMaxBufferLength = reducedLength; @@ -1581,6 +1587,7 @@ export default class BaseStreamController protected reduceLengthAndFlushBuffer(data: ErrorData): boolean { // if in appending state if (this.state === State.PARSING || this.state === State.PARSED) { + const frag = data.frag; const playlistType = data.parent as PlaylistLevelType; const bufferedInfo = this.getFwdBufferInfo( this.mediaBuffer, @@ -1590,7 +1597,7 @@ export default class BaseStreamController // reduce max buf len if current position is buffered const buffered = bufferedInfo && bufferedInfo.len > 0.5; if (buffered) { - this.reduceMaxBufferLength(bufferedInfo.len); + this.reduceMaxBufferLength(bufferedInfo.len, frag?.duration || 10); } const flushBuffer = !buffered; if (flushBuffer) { @@ -1601,9 +1608,9 @@ export default class BaseStreamController `Buffer full error while media.currentTime is not buffered, flush ${playlistType} buffer`, ); } - if (data.frag) { - this.fragmentTracker.removeFragment(data.frag); - this.nextLoadPosition = data.frag.start; + if (frag) { + this.fragmentTracker.removeFragment(frag); + this.nextLoadPosition = frag.start; } this.resetLoadingState(); return flushBuffer;