Skip to content

Commit 1e5731b

Browse files
authored
Merge pull request #11 from roboflow/handling-turn-server-instability
ack implementation on client side
2 parents dac7c01 + 321cee2 commit 1e5731b

File tree

1 file changed

+23
-2
lines changed

1 file changed

+23
-2
lines changed

src/webrtc.ts

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,7 @@ export class RFWebRTCConnection {
323323
*/
324324
public readonly dataChannel: RTCDataChannel;
325325
private reassembler: ChunkReassembler;
326+
private ackPacingEnabled: boolean;
326327
/**
327328
* The data channel used for uploading video files (only available in file upload mode).
328329
* Exposed for advanced use cases.
@@ -343,6 +344,8 @@ export class RFWebRTCConnection {
343344
uploadChannel?: RTCDataChannel;
344345
onData?: (data: any) => void;
345346
onComplete?: () => void;
347+
/** @internal Enable server pacing via cumulative ACKs (only used when realtimeProcessing=false). */
348+
ackPacingEnabled?: boolean;
346349
}
347350
) {
348351
this.peerConnection = pc;
@@ -352,6 +355,7 @@ export class RFWebRTCConnection {
352355
this.apiKey = apiKey;
353356
this.dataChannel = dataChannel;
354357
this.reassembler = new ChunkReassembler();
358+
this.ackPacingEnabled = options?.ackPacingEnabled === true;
355359
this.uploadChannel = options?.uploadChannel;
356360
this.onComplete = options?.onComplete;
357361

@@ -374,7 +378,11 @@ export class RFWebRTCConnection {
374378
const decoder = new TextDecoder("utf-8");
375379
const jsonString = decoder.decode(completePayload);
376380
const data = JSON.parse(jsonString);
377-
onData(data);
381+
// Wait for onData completion (supports async handlers) before ACKing the frame.
382+
Promise.resolve(onData(data))
383+
.finally(() => {
384+
this.maybeSendAck(frameId);
385+
})
378386
}
379387
} else {
380388
// Fallback for string messages (shouldn't happen with new protocol)
@@ -400,6 +408,17 @@ export class RFWebRTCConnection {
400408
});
401409
}
402410

411+
/**
412+
* Send cumulative ACK after a frame is fully handled.
413+
* Only used in batch mode (realtimeProcessing=false).
414+
*/
415+
private maybeSendAck(frameId: number): void {
416+
if (!this.ackPacingEnabled) return;
417+
if (this.dataChannel.readyState !== "open") return;
418+
419+
this.dataChannel.send(JSON.stringify({ ack: frameId }));
420+
}
421+
403422
/**
404423
* Get the remote stream (processed video from Roboflow)
405424
*
@@ -706,6 +725,7 @@ async function baseUseStream({
706725
const apiKey = connector._apiKey || null;
707726

708727
// Step 7: Create connection object
728+
const ackPacingEnabled = resolvedWrtcParams.realtimeProcessing === false;
709729
const connection = new RFWebRTCConnection(
710730
pc,
711731
remoteStreamPromise,
@@ -716,7 +736,8 @@ async function baseUseStream({
716736
localStream,
717737
uploadChannel,
718738
onData,
719-
onComplete
739+
onComplete,
740+
ackPacingEnabled
720741
}
721742
);
722743

0 commit comments

Comments
 (0)