@@ -41,7 +41,9 @@ let micWorkletNode = null;
41
41
let preferredInputDeviceId = null ;
42
42
let preferredOutputDeviceId = null ;
43
43
let metricsIntervalId = null ;
44
+ let backpressureIntervalId = null ;
44
45
const METRICS_INTERVAL_MS = 500 ;
46
+ const BACKPRESSURE_INTERVAL_MS = 50 ;
45
47
const UPLOAD_CHUNK_SIZE = ( 1024 * 1024 ) - 1 ;
46
48
const FILE_UPLOAD_THROTTLE_MS = 200 ;
47
49
let fileUploadProgressLastSent = { } ;
@@ -2508,6 +2510,18 @@ function handleDecodedFrame(frame) { // frame.codedWidth/Height are physical pix
2508
2510
websocket = new WebSocket ( websocketEndpointURL . href ) ;
2509
2511
websocket . binaryType = 'arraybuffer' ;
2510
2512
2513
+ const sendBackpressureAck = ( ) => {
2514
+ if ( websocket && websocket . readyState === WebSocket . OPEN ) {
2515
+ try {
2516
+ if ( lastReceivedVideoFrameId !== - 1 ) {
2517
+ websocket . send ( `CLIENT_FRAME_ACK ${ lastReceivedVideoFrameId } ` ) ;
2518
+ }
2519
+ } catch ( error ) {
2520
+ console . error ( '[Backpressure] Error sending frame ACK:' , error ) ;
2521
+ }
2522
+ }
2523
+ } ;
2524
+
2511
2525
const sendClientMetrics = ( ) => {
2512
2526
if ( isSharedMode ) return ; // Shared mode does not have client-side FPS display in this context
2513
2527
@@ -2548,21 +2562,6 @@ function handleDecodedFrame(frame) { // frame.codedWidth/Height are physical pix
2548
2562
} ) ;
2549
2563
}
2550
2564
}
2551
-
2552
- if ( websocket && websocket . readyState === WebSocket . OPEN ) {
2553
- if ( audioWorkletProcessorPort ) {
2554
- audioWorkletProcessorPort . postMessage ( {
2555
- type : 'getBufferSize'
2556
- } ) ;
2557
- }
2558
- try {
2559
- if ( lastReceivedVideoFrameId !== - 1 ) {
2560
- websocket . send ( `CLIENT_FRAME_ACK ${ lastReceivedVideoFrameId } ` ) ;
2561
- }
2562
- } catch ( error ) {
2563
- console . error ( '[websockets] Error sending client metrics (ACK):' , error ) ;
2564
- }
2565
- }
2566
2565
} ;
2567
2566
2568
2567
websocket . onopen = ( ) => {
@@ -2702,6 +2701,10 @@ function handleDecodedFrame(frame) { // frame.codedWidth/Height are physical pix
2702
2701
metricsIntervalId = setInterval ( sendClientMetrics , METRICS_INTERVAL_MS ) ;
2703
2702
console . log ( `[websockets] Started sending client metrics every ${ METRICS_INTERVAL_MS } ms.` ) ;
2704
2703
}
2704
+ if ( backpressureIntervalId === null ) {
2705
+ backpressureIntervalId = setInterval ( sendBackpressureAck , BACKPRESSURE_INTERVAL_MS ) ;
2706
+ console . log ( `[websockets] Started sending backpressure ACKs every ${ BACKPRESSURE_INTERVAL_MS } ms.` ) ;
2707
+ }
2705
2708
}
2706
2709
} ;
2707
2710
@@ -3258,6 +3261,10 @@ function handleDecodedFrame(frame) { // frame.codedWidth/Height are physical pix
3258
3261
clearInterval ( metricsIntervalId ) ;
3259
3262
metricsIntervalId = null ;
3260
3263
}
3264
+ if ( backpressureIntervalId ) {
3265
+ clearInterval ( backpressureIntervalId ) ;
3266
+ backpressureIntervalId = null ;
3267
+ }
3261
3268
releaseWakeLock ( ) ;
3262
3269
if ( isSharedMode ) {
3263
3270
console . error ( "Shared mode: WebSocket error. Resetting shared state to 'error'." ) ;
@@ -3276,6 +3283,10 @@ function handleDecodedFrame(frame) { // frame.codedWidth/Height are physical pix
3276
3283
clearInterval ( metricsIntervalId ) ;
3277
3284
metricsIntervalId = null ;
3278
3285
}
3286
+ if ( backpressureIntervalId ) {
3287
+ clearInterval ( backpressureIntervalId ) ;
3288
+ backpressureIntervalId = null ;
3289
+ }
3279
3290
releaseWakeLock ( ) ;
3280
3291
cleanupVideoBuffer ( ) ;
3281
3292
cleanupJpegStripeQueue ( ) ;
@@ -3591,6 +3602,10 @@ function cleanup() {
3591
3602
clearInterval ( metricsIntervalId ) ;
3592
3603
metricsIntervalId = null ;
3593
3604
}
3605
+ if ( backpressureIntervalId ) {
3606
+ clearInterval ( backpressureIntervalId ) ;
3607
+ backpressureIntervalId = null ;
3608
+ }
3594
3609
releaseWakeLock ( ) ;
3595
3610
if ( window . isCleaningUp ) return ;
3596
3611
window . isCleaningUp = true ;
0 commit comments