@@ -301,6 +301,9 @@ export class SabrStream extends PassThrough {
301301 this . enableTrafficDump = true ;
302302 this . trafficDumpMaxBytes = 64 * 1024 ;
303303
304+ this . bandwidthEstimate = 5000000 ;
305+ this . lastBandwidthLogAt = 0 ;
306+
304307 this . noMediaStreak = 0 ;
305308 this . abortController = new AbortController ( ) ;
306309
@@ -319,6 +322,21 @@ export class SabrStream extends PassThrough {
319322 void appendFile ( this . trafficLogPath , JSON . stringify ( entry ) + '\n' ) . catch ( ( ) => { } ) ;
320323 }
321324
325+ updateBandwidthEstimate ( bytes , durationMs ) {
326+ if ( bytes <= 0 || durationMs <= 0 ) return ;
327+
328+ const bits = bytes * 8 ;
329+ const throughput = ( bits / durationMs ) * 1000 ;
330+
331+ const alpha = 0.15 ;
332+ this . bandwidthEstimate = ( alpha * throughput ) + ( ( 1 - alpha ) * this . bandwidthEstimate ) ;
333+
334+ if ( Date . now ( ) - this . lastBandwidthLogAt > 2000 ) {
335+ this . lastBandwidthLogAt = Date . now ( ) ;
336+ logger ( 'debug' , 'SABR' , `Bandwidth Update: measured=${ ( throughput / 1000000 ) . toFixed ( 2 ) } Mbps est=${ ( this . bandwidthEstimate / 1000000 ) . toFixed ( 2 ) } Mbps` ) ;
337+ }
338+ }
339+
322340 start ( audioItag ) {
323341 const audioFormat = this . formatIds . find ( f => f . itag === audioItag ) ;
324342 if ( ! audioFormat ) {
@@ -397,7 +415,7 @@ export class SabrStream extends PassThrough {
397415 try {
398416 await this . fetchAndProcessSegments ( {
399417 playerTimeMs : Math . floor ( this . totalDownloadedMs ) ,
400- bandwidthEstimate : 15000000 ,
418+ bandwidthEstimate : Math . max ( Math . floor ( this . bandwidthEstimate ) , 500000 ) ,
401419 enabledTrackTypesBitfield : 1 ,
402420 audioTrackId : audioFormat . audioTrackId || "" ,
403421 playerState : 1n ,
@@ -1194,11 +1212,16 @@ export class SabrStream extends PassThrough {
11941212 buffer = ump . compositeBuffer ;
11951213 }
11961214 } catch ( err ) {
1197- // AbortError (or equivalent) during destroy/abort should not crash the stream.
11981215 if ( ! ( this . _aborted || this . destroyed || signal . aborted ) ) throw err ;
11991216 } finally {
12001217 try { await reader . cancel ( ) ; } catch { }
12011218 try { reader . releaseLock ( ) ; } catch { }
1219+ const totalDuration = Date . now ( ) - t0 ;
1220+ if ( responseBytes > 0 && totalDuration > 0 ) {
1221+ if ( saw . media || responseBytes > 5000 ) {
1222+ this . updateBandwidthEstimate ( responseBytes , totalDuration ) ;
1223+ }
1224+ }
12021225 }
12031226
12041227
0 commit comments